Skip to content

Enum cheatsheet ​

Source: Elixir cheatsheet, Enum.

A quick reference for Enum, the module for working with enumerables. Most examples use this cart:

elixir
cart = [
  %{fruit: "apple", count: 3},
  %{fruit: "banana", count: 1},
  %{fruit: "orange", count: 6}
]

A few use string =~ part, which checks that the string on the left contains the part on the right.

Which function? ​

Start from what you want back:

Find the group by the result you want.

Predicates ​

Functions that answer yes or no.

FunctionExampleResult
any?(enum, fun)Enum.any?(cart, & &1.fruit == "orange")true
Enum.any?(cart, & &1.fruit == "pear")false
all?(enum, fun)Enum.all?(cart, & &1.count > 0)true
Enum.all?(cart, & &1.count > 1)false
member?(enum, value)Enum.member?(cart, %{fruit: "apple", count: 3})true
empty?(enum)Enum.empty?([])true

any? on an empty collection is always false. all? on an empty collection is always true. item in enum is the same as Enum.member?(enum, item).

Filtering ​

filter keeps what matches. reject drops it.
FunctionExampleResult
filter(enum, fun)Enum.filter(cart, &(&1.fruit =~ "o"))[%{fruit: "orange", count: 6}]
Enum.filter(cart, &(&1.fruit =~ "e"))apple and orange
reject(enum, fun)Enum.reject(cart, &(&1.fruit =~ "o"))apple and banana
flat_map(enum, fun)Enum.flat_map(cart, fn item -> if item.count > 1, do: [item.fruit], else: [] end)["apple", "orange"]

flat_map filters and transforms in one pass: return [] to exclude an element. Comprehensions filter too, with a condition (for item <- cart, item.fruit =~ "e", do: item) or with a pattern in the generator (for %{count: 1, fruit: fruit} <- cart, do: fruit gives ["banana"]).

Mapping ​

FunctionExampleResult
map(enum, fun)Enum.map(cart, & &1.fruit)["apple", "banana", "orange"]
Enum.map(cart, fn item -> %{item | count: item.count + 10} end)counts 13, 11, 16
map_every(enum, nth, fun)Enum.map_every(cart, 2, fn item -> %{item | count: item.count + 10} end)counts 13, 1, 16

map_every(…, 2, …) applies the function to the 1st, 3rd, 5th… element. With a comprehension: for item <- cart, do: item.fruit, and filter plus map at once with for item <- cart, item.fruit =~ "e", do: item.fruit (["apple", "orange"]).

Side effects ​

FunctionExampleResult
each(enum, fun)Enum.each(cart, &IO.puts(&1.fruit))prints the three names, returns :ok

each is used only for side effects.

Accumulating ​

One list of counts, four ways to accumulate.
FunctionExampleResult
reduce(enum, acc, fun)Enum.reduce(cart, 0, fn item, acc -> item.count + acc end)10
map_reduce(enum, acc, fun)Enum.map_reduce(cart, 0, fn item, acc -> {item.fruit, item.count + acc} end){["apple", "banana", "orange"], 10}
scan(enum, acc, fun)Enum.scan(cart, 0, fn item, acc -> item.count + acc end)[3, 4, 10]
reduce_while(enum, acc, fun)halt with {:halt, acc} at "orange", otherwise {:cont, item.count + acc}4

Comprehensions can reduce too: for item <- cart, reduce: 0 do acc -> item.count + acc end gives 10, and with a filter (item.fruit =~ "e") gives 9.

Aggregations ​

FunctionExampleResult
count(enum)Enum.count(cart)3
count(enum, fun)Enum.count(cart, &(&1.fruit =~ "e"))2
frequencies(enum)Enum.frequencies(["apple", "banana", "orange", "apple"])%{"apple" => 2, "banana" => 1, "orange" => 1}
frequencies_by(enum, key_fun)Enum.frequencies_by(cart, &String.last(&1.fruit))%{"a" => 1, "e" => 2}
sum(enum)cart |> Enum.map(& &1.count) |> Enum.sum()10
sum_by(enum, mapper)Enum.sum_by(cart, & &1.count)10
product(enum)cart |> Enum.map(& &1.count) |> Enum.product()18
product_by(enum, mapper)Enum.product_by(cart, & &1.count)18

Prefer sum_by/2 and product_by/2: one pass instead of two. Enum.count_until/2,3 counts up to a limit.

Sorting ​

FunctionExampleResult
sort(enum, sorter \\ :asc)cart |> Enum.map(& &1.fruit) |> Enum.sort()apple, banana, orange
… |> Enum.sort(:desc)orange, banana, apple
sort_by(enum, mapper, sorter \\ :asc)Enum.sort_by(cart, & &1.count)banana (1), apple (3), orange (6)
Enum.sort_by(cart, & &1.count, :desc)orange, apple, banana
min(enum) / max(enum)cart |> Enum.map(& &1.count) |> Enum.min()1 (max: 6)
min_by(enum, mapper)Enum.min_by(cart, & &1.count)%{fruit: "banana", count: 1}
max_by(enum, mapper)Enum.max_by(cart, & &1.count)%{fruit: "orange", count: 6}

When sorting or comparing structs, pass a module as the sorter (Enum.sort/2, sort_by/3, min/2, min_by/3, max/2, max_by/3).

Concatenating and flattening ​

flat_map is map followed by a one-level flatten.
FunctionExampleResult
concat(enums)Enum.concat([[1, 2, 3], [4, 5, 6], [7, 8, 9]])[1, 2, 3, 4, 5, 6, 7, 8, 9]
concat(left, right)Enum.concat([1, 2, 3], [4, 5, 6])[1, 2, 3, 4, 5, 6]
flat_map(enum, fun)Enum.flat_map(cart, fn item -> List.duplicate(item.fruit, item.count) end)apple ×3, banana, orange ×6
flat_map_reduce(enum, acc, fun)same, returning {list, acc + item.count}{that list, 10}

Two generators in a comprehension flatten too: for item <- cart, fruit <- List.duplicate(item.fruit, item.count), do: fruit.

Conversion ​

FunctionExampleResult
into(enum, collectable)Enum.into([{"apple", 3}, {"banana", 1}, {"orange", 6}], %{})%{"apple" => 3, "banana" => 1, "orange" => 6}
into(enum, collectable, transform)Enum.into(cart, %{}, fn item -> {item.fruit, item.count} end)the same map
to_list(enum)Enum.to_list(1..5)[1, 2, 3, 4, 5]

The comprehension form is for item <- cart, into: %{}, do: {item.fruit, item.count}.

Every comprehension option has an Enum function.

Duplicates and uniques ​

dedup only sees neighbours. uniq sees everything.
FunctionExampleResult
dedup(enum)Enum.dedup([1, 2, 2, 3, 3, 3, 1, 2, 3])[1, 2, 3, 1, 2, 3]
dedup_by(enum, fun)Enum.dedup_by(cart, & &1.fruit =~ "a")just the apple
Enum.dedup_by(cart, & &1.count < 5)apple and orange
uniq(enum)Enum.uniq([1, 2, 2, 3, 3, 3, 1, 2, 3])[1, 2, 3]
uniq_by(enum, fun)Enum.uniq_by(cart, &String.last(&1.fruit))apple and banana

Comprehensions support uniq: true.

Indexing ​

FunctionExampleResult
at(enum, index, default \\ nil)Enum.at(cart, 0)the apple map
Enum.at(cart, 10) / Enum.at(cart, 10, :none)nil / :none
fetch(enum, index)Enum.fetch(cart, 0) / Enum.fetch(cart, 10){:ok, apple map} / :error
fetch!(enum, index)Enum.fetch!(cart, 10)raises Enum.OutOfBoundsError
with_index(enum)Enum.with_index(cart)[{apple map, 0}, {banana map, 1}, {orange map, 2}]
with_index(enum, fun)Enum.with_index(cart, fn item, index -> {item.fruit, index} end)[{"apple", 0}, {"banana", 1}, {"orange", 2}]

Indexing into a list in a loop is discouraged: lists are linked lists.

Finding ​

FunctionExampleResult
find(enum, default \\ nil, fun)Enum.find(cart, &(&1.fruit =~ "o"))the orange map
Enum.find(cart, &(&1.fruit =~ "y")) / with default :nonenil / :none
find_index(enum, fun)Enum.find_index(cart, &(&1.fruit =~ "o"))2 (nil if none)
find_value(enum, default \\ nil, fun)Enum.find_value(cart, fn item -> if item.count == 1, do: item.fruit end)"banana"

find_value returns the first truthy result of the function, not the element.

Grouping ​

The key function decides the group.
FunctionExampleResult
group_by(enum, key_fun)Enum.group_by(cart, &String.last(&1.fruit))%{"a" => [banana map], "e" => [apple map, orange map]}
group_by(enum, key_fun, value_fun)Enum.group_by(cart, &String.last(&1.fruit), & &1.fruit)%{"a" => ["banana"], "e" => ["apple", "orange"]}

Joining and interspersing ​

FunctionExampleResult
join(enum, joiner \\ "")Enum.join(["apple", "banana", "orange"], ", ")"apple, banana, orange"
map_join(enum, joiner \\ "", mapper)Enum.map_join(cart, ", ", & &1.fruit)"apple, banana, orange"
intersperse(enum, separator \\ "")Enum.intersperse(["apple", "banana", "orange"], ", ")["apple", ", ", "banana", ", ", "orange"]
map_intersperse(enum, separator \\ "", mapper)Enum.map_intersperse(cart, ", ", & &1.fruit)the same list

Slicing ​

FunctionExampleResult
slice(enum, index_range)Enum.slice(cart, 0..1)apple, banana
Enum.slice(cart, -2..-1)banana, orange (negative counts from the back)
slice(enum, start_index, amount)Enum.slice(cart, 1, 2)banana, orange
slide(enum, range_or_index, insertion_index)Enum.slide(fruits, 2, 0)["grape", "apple", "banana", "orange", "pear"]
Enum.slide(fruits, 1..3, 4)["apple", "pear", "banana", "grape", "orange"]

Those slide examples use fruits = ["apple", "banana", "grape", "orange", "pear"].

Reversing ​

FunctionExampleResult
reverse(enum)Enum.reverse(cart)orange, banana, apple
reverse(enum, tail)Enum.reverse(cart, [:this_will_be, :the_tail])the reversed cart, then :this_will_be, :the_tail
reverse_slice(enum, start_index, count)Enum.reverse_slice(cart, 1, 2)apple, orange, banana

Splitting ​

split_while stops early. split_with checks everything.
FunctionExampleResult
split(enum, amount)Enum.split(cart, 1){[apple], [banana, orange]}
Enum.split(cart, -1){[apple, banana], [orange]}
split_while(enum, fun)Enum.split_while(cart, &(&1.fruit =~ "e")){[apple], [banana, orange]}
split_with(enum, fun)Enum.split_with(cart, &(&1.fruit =~ "e")){[apple, orange], [banana]}

Drop and take ​

FunctionExampleResult
drop(enum, amount)Enum.drop(cart, 1) / Enum.drop(cart, -1)banana, orange / apple, banana
drop_every(enum, nth)Enum.drop_every(cart, 2)[banana map]
drop_while(enum, fun)Enum.drop_while(cart, &(&1.fruit =~ "e"))banana, orange
take(enum, amount)Enum.take(cart, 1) / Enum.take(cart, -1)[apple map] / [orange map]
take_every(enum, nth)Enum.take_every(cart, 2)apple, orange
take_while(enum, fun)Enum.take_while(cart, &(&1.fruit =~ "e"))[apple map]

Negative amounts count from the back.

Random ​

FunctionExampleResult
random(enum)Enum.random(cart)one element, different each call
take_random(enum, count)Enum.take_random(cart, 2)two elements, different each call
shuffle(enum)Enum.shuffle(cart)the cart in a random order

Chunking ​

Fixed-size chunks, sliding windows, or chunks that follow a value.
FunctionExampleResult
chunk_by(enum, fun)Enum.chunk_by(cart, &String.length(&1.fruit))[[apple], [banana, orange]]
chunk_every(enum, count)Enum.chunk_every(cart, 2)[[apple, banana], [orange]]
chunk_every(enum, count, step, leftover \\ [])Enum.chunk_every(cart, 2, 2, [:elements, :to_complete])[[apple, banana], [orange, :elements]]
Enum.chunk_every(cart, 2, 1, :discard)[[apple, banana], [banana, orange]]

See Enum.chunk_while/4 for custom chunking.

Zipping ​

zip pairs elements by position. unzip splits them again.

With fruits = ["apple", "banana", "orange"] and counts = [3, 1, 6]:

FunctionExampleResult
zip(enum1, enum2)Enum.zip(fruits, counts)[{"apple", 3}, {"banana", 1}, {"orange", 6}]
zip_with(enum1, enum2, fun)Enum.zip_with(fruits, counts, fn fruit, count -> %{fruit: fruit, count: count} end)the cart
zip_reduce(left, right, acc, fun)price is count * 2 if fruit =~ "e", else count, summed from 019
unzip(list)cart |> Enum.map(&{&1.fruit, &1.count}) |> Enum.unzip(){["apple", "banana", "orange"], [3, 1, 6]}

Enum.zip/1, zip_with/2 and zip_reduce/3 zip many collections at once.

Site code: MIT. Pages and diagrams are derived from the Elixir documentation (Apache-2.0). Not affiliated with the Elixir Team.