Fork me on GitHub

Enum

Αυτή η μετάφραση είναι πλήρως ενημερωμένη.

Μια συλλογή αλγορίθμων για την απαρίθμηση συλλογών.

Πίνακας περιεχομένων

Enum

Η ενότητα Enum περιλαμβάνει πάνω από εβδομήντα συναρτήσεις για την εργασία με τις συλλογές. Όλες οι συλλογές που μάθαμε στο προηγούμενο μάθημα, με την εξαίρεση των τούπλων, είναι απαριθμήσιμες.

Αυτό το μάθημα θα καλύψει μόνο ένα μέρος των διαθέσιμων συναρτήσεων, αλλά μπορούμε να τις ελέγξουμε μόνοι μας. Ας κάνουμε ένα μικρό πείραμα στο IEx.

iex> Enum.__info__(:functions) |> Enum.each(fn({function, arity}) ->
...>  IO.puts "#{function}/#{arity}"
...>end)
all?/1
all?/2
any?/1
any?/2
at/2
at/3
...

Με την παραπάνω εξόδο, είναι ξεκάθαρο ότι έχουμε ένα πολύ μεγάλο ποσό λειτουργιών, και για έναν καλό λόγο. Η απαρίθμηση βρίσκεται στον πυρήνα του συναρτησιακού προγραμματισμού και είναι ένα εξαιρετικά χρήσιμο πράγμα. Η αξιοποίηση του μαζί με άλλα στοιχεία της Elixir, όπως το βάρος που έχει δωθεί στην τεκμηρίωση όπως είδαμε, μπορεί να δώσει απίστευτη δύναμη σε έναν προγραμματιστή.

Για να δείτε τις συναρτήσεις στο σύνολό τους επισκεφθείτε τα επίσημα έγγραφα του Enum. Για τεμπέλικη απαρίθμηση (lazy enumeration) χρησιμοποιήστε την ενότητα Stream.

all?

Όταν χρησιμοποιούμε την all?, και το μεγαλύτερο μέρος της Enum, παρέχουμε μια συνάρτηση την οποία εφαρμόζουμε σε όλα τα στοιχεία της συλλογής. Στην περίπτωση της all?, όλη η συλλογή πρέπει να επιστρέφει true, αλλιώς θα επιστρέψει false:

iex> Enum.all?(["foo", "bar", "hello"], fn(s) -> String.length(s) == 3 end)
false
iex> Enum.all?(["foo", "bar", "hello"], fn(s) -> String.length(s) > 1 end)
true

any?

Αντίθετα με την προηγούμενη, η any? θα επιστρέψει true αν τουλάχιστον ένα στοιχείο αξιολογηθεί σαν true:

iex> Enum.any?(["foo", "bar", "hello"], fn(s) -> String.length(s) == 5 end)
true

chunk_every/2

Αν χρειαστεί να σπάσουμε την συλλογή σε μικρότερα μέρη, η chunk_every/4 είναι μάλλον η συνάρτηση που ψάχνουμε:

iex> Enum.chunk_every([1, 2, 3, 4, 5, 6], 2)
[[1, 2], [3, 4], [5, 6]]

Yπάρχουν μερικές επιλογές για την chunk_every/4 αλλά δεν θα τις αναλύσουμε, για να μάθετε περισσότερα επισκεφθείτε την chunk_every/4 στα επίσημα κείμενα.

chunk_by

Αν χρειάστει να ομαδοποιήσουμε την συλλογή μας βασιζόμενοι σε κάτι πέραν του μεγέθους, μπορούμε να χρησιμοποιήσουμε τη συνάρτηση chunk_by/2. Δέχεται μια συλλογή και μια συνάρτηση, και όταν αλλάζει η επιστροφή της συνάρτησης, ξεκινάει μια νέα ομάδα:

iex> Enum.chunk_by(["one", "two", "three", "four", "five"], fn(x) -> String.length(x) end)
[["one", "two"], ["three"], ["four", "five"]]
iex> Enum.chunk_by(["one", "two", "three", "four", "five", "six"], fn(x) -> String.length(x) end)
[["one", "two"], ["three"], ["four", "five"], ["six"]]

map_every

Μερικές φορές η ομαδοποίηση μιας συλλογής δεν είναι αρκετή για αυτό που πρέπει να κάνουμε. Αν αυτό ισχύει, η map_every/3 μπορεί να είναι πολύ χρήσιμη για να έχετε πρόσβαση σε κάθε νιοστό στοιχείο, εφαρμόζοντας πάντα τη συνάρτηση στο πρώτο στοιχείο:

# Εφαρμόστε συνάρτηση σε κάθε τρίτο στοιχείο
iex> Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8], 3, fn x -> x + 1000 end)
[1001, 2, 3, 1004, 5, 6, 1007, 8]

each

Μπορεί να είναι απαραίτητο να περάσετε όλη τη συλλογή χωρίς να παραχθεί νέα τιμή. Σε αυτή την περίπτωση χρησιμοποιούμε την each/2:

iex> Enum.each(["one", "two", "three"], fn(s) -> IO.puts(s) end)
one
two
three
:ok

Σημείωση: Η συνάρτηση each/2 επιστρέφει το άτομο :ok.

map

Για να εφαρμόσουμε την συνάρτησή μας σε κάθε αντικείμενο και να φτιάξουμε μια νέα συλλογή πρέπει να απευθυνθούμε στην συνάρτηση map/2:

iex> Enum.map([0, 1, 2, 3], fn(x) -> x - 1 end)
[-1, 0, 1, 2]

min

Η min/1 βρίσκει τη μικρότερη τιμή σε μια συλλογή:

iex> Enum.min([5, 3, 0, -1])
-1

Η min/2 κάνει το ίδιο, αλλά σε περίπτωση που η απαρίθμηση είναι κενή, μας επιτρέπει να ορίσουμε μια συνάρτηση για να παράξουμε την μικρότερη τιμή:

iex> Enum.min([], fn -> :foo end)
:foo

max

Η max/1 επιστρέφει τη μεγαλύτερη τιμή στη συλλογή:

iex> Enum.max([5, 3, 0, -1])
5

Η max/2 είναι για την max/1 ότι η min/2 για την min/1:

Enum.max([], fn -> :bar end)
:bar

reduce

Με την reduce/3 μπορούμε να μαζέψουμε την συλλογή μας σε μία τιμή. Για να το κάνουμε αυτό, παρέχουμε έναν προεραιτικό συσσωρευτή (το 10 σε αυτό το παράδειγμα) ο οποίος περνάει στη συνάρτηση. Αν δεν παρέχουμε συσσωρευτή, χρησιμοποιείται η πρώτη τιμή:

iex> Enum.reduce([1, 2, 3], 10, fn(x, acc) -> x + acc end)
16

iex> Enum.reduce([1, 2, 3], fn(x, acc) -> x + acc end)
6

iex> Enum.reduce(["a","b","c"], "1", fn(x,acc)-> x <> acc end)
"cba1"

sort

Η ταξινόμηση των συλλογών μας γίνεται εύκολη όχι με μία, αλλά με δύο συναρτήσεις ταξινόμησης.

Η sort/1 χρησιμοποιεί την ταξινόμηση όρων της Erlang για να καθορίσει την σειρά ταξινόμησης:

iex> Enum.sort([5, 6, 1, 3, -1, 4])
[-1, 1, 3, 4, 5, 6]

iex> Enum.sort([:foo, "bar", Enum, -1, 4])
[-1, 4, Enum, :foo, "bar"]

Όμως η sort/2 μας επιτρέπει να παρέχουμε μια δική μας συνάρτηση ταξινόμησης:

# με τη συνάρτησή μας
iex> Enum.sort([%{:val => 4}, %{:val => 1}], fn(x, y) -> x[:val] > y[:val] end)
[%{val: 4}, %{val: 1}]

# χωρίς
iex> Enum.sort([%{:count => 4}, %{:count => 1}])
[%{count: 1}, %{count: 4}]

uniq

Μπορούμε να χρησιμοποιήσουμε την uniq για να αφαιρέσουμε διπλότυπα από τις συλλογές μας:

iex> Enum.uniq([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
[1, 2, 3, 4]

Contributors

loading...



Share This Page