The Enum module is probably the most used of all the Elixir libraries. Employ it to iterate, filter, combine, split, and otherwise manipulate collections. Here are some common tasks:
Convert any collection into a list:
| iex> list = Enum.to_list 1..5 |
| [1, 2, 3, 4, 5] |
Concatenate collections:
| iex> Enum.concat([1,2,3], [4,5,6]) |
| [1, 2, 3, 4, 5, 6] |
| iex> Enum.concat [1,2,3], 'abc' |
| [1, 2, 3, 97, 98, 99] |
Create collections whose elements are some function of the original:
| iex> Enum.map(list, &(&1 * 10)) |
| [10, 20, 30, 40, 50] |
| iex> Enum.map(list, &String.duplicate("*", &1)) |
| ["*", "**", "***", "****", "*****"] |
Select elements by position or criteria:
| iex> Enum.at(10..20, 3) |
| 13 |
| iex> Enum.at(10..20, 20) |
| nil |
| iex> Enum.at(10..20, 20, :no_one_here) |
| :no_one_here |
| iex> Enum.filter(list, &(&1 > 2)) |
| [3, 4, 5] |
| iex> require Integer # to get access to is_even |
| Integer |
| iex> Enum.filter(list, &Integer.is_even/1) |
| [2, 4] |
| iex> Enum.reject(list, &Integer.is_even/1) |
| [1, 3, 5] |
Sort and compare elements:
| iex> Enum.sort ["there", "was", "a", "crooked", "man"] |
| ["a", "crooked", "man", "there", "was"] |
| iex> Enum.sort ["there", "was", "a", "crooked", "man"], |
| ...> &(String.length(&1) <= String.length(&2)) |
| ["a", "was", "man", "there", "crooked"] |
| iex(4)> Enum.max ["there", "was", "a", "crooked", "man"] |
| "was" |
| iex(5)> Enum.max_by ["there", "was", "a", "crooked", "man"], &String.length/1 |
| "crooked" |
Split a collection:
| iex> Enum.take(list, 3) |
| [1, 2, 3] |
| iex> Enum.take_every list, 2 |
| [1, 3, 5] |
| iex> Enum.take_while(list, &(&1 < 4)) |
| [1, 2, 3] |
| iex> Enum.split(list, 3) |
| {[1, 2, 3], [4, 5]} |
| iex> Enum.split_while(list, &(&1 < 4)) |
| {[1, 2, 3], [4, 5]} |
Join a collection:
| iex> Enum.join(list) |
| "12345" |
| iex> Enum.join(list, ", ") |
| "1, 2, 3, 4, 5" |
Predicate operations:
| iex> Enum.all?(list, &(&1 < 4)) |
| false |
| iex> Enum.any?(list, &(&1 < 4)) |
| true |
| iex> Enum.member?(list, 4) |
| true |
| iex> Enum.empty?(list) |
| false |
Merge collections:
| iex> Enum.zip(list, [:a, :b, :c]) |
| [{1, :a}, {2, :b}, {3, :c}] |
| iex> Enum.with_index(["once", "upon", "a", "time"]) |
| [{"once", 0}, {"upon", 1}, {"a", 2}, {"time", 3}] |
Fold elements into a single value:
| iex> Enum.reduce(1..100, &(&1+&2)) |
| 5050 |
| iex> Enum.reduce(["now", "is", "the", "time"],fn word, longest -> |
| ...> if String.length(word) > String.length(longest) do |
| ...> word |
| ...> else |
| ...> longest |
| ...> end |
| ...> end) |
| "time" |
| iex> Enum.reduce(["now", "is", "the", "time"], 0, fn word, longest -> |
| ...> if String.length(word) > longest, |
| ...> do: String.length(word), |
| ...> else: longest |
| ...> end) |
| 4 |
Deal a hand of cards:
| iex> import Enum |
| iex> deck = for rank <- '23456789TJQKA', suit <- 'CDHS', do: [suit,rank] |
| ['C2', 'D2', 'H2', 'S2', 'C3', 'D3', ... ] |
| iex> deck |> shuffle |> take(13) |
| ['DQ', 'S6', 'HJ', 'H4', 'C7', 'D6', 'SJ', 'S9', 'D7', 'HA', 'S4', 'C2', 'CT'] |
| iex> hands = deck |> shuffle |> chunk(13) |
| [['D8', 'CQ', 'H2', 'H3', 'HK', 'H9', 'DK', 'S9', 'CT', 'ST', 'SK', 'D2', 'HA'], |
| ['C5', 'S3', 'CK', 'HQ', 'D3', 'D4', 'CA', 'C8', 'S6', 'DQ', 'H5', 'S2', 'C4'], |
| ['C7', 'C6', 'C2', 'D6', 'D7', 'SA', 'SQ', 'H8', 'DT', 'C3', 'H7', 'DA', 'HT'], |
| ['S5', 'S4', 'C9', 'S8', 'D5', 'H4', 'S7', 'SJ', 'HJ', 'D9', 'DJ', 'CJ', 'H6']] |
In our example of sort, we used
| iex> Enum.sort ["there", "was", "a", "crooked", "man"], |
| ...> &(String.length(&1) <= String.length(&2)) |
It’s important to use <= and not just < if you want the sort to be stable.