Enum cheatsheet — Elixir v1.16.3

Search documentation of Elixir

# View Source
Enum cheatsheet

A quick reference into the `Enum` module, a module for working with collections (known as enumerables). Most of the examples below use the following data structure:

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

Some examples use the `string =~ part` operator, which checks the string on the left contains the part on the right.

## Predicates

### `any?(enum, fun)`

    iex> Enum.any?(cart, & &1.fruit == "orange")
    true
    iex> Enum.any?(cart, & &1.fruit == "pear")
    false

`any?` with an empty collection is always false:

    iex> Enum.any?([], & &1.fruit == "orange")
    false

### `all?(enum, fun)`

    iex> Enum.all?(cart, & &1.count > 0)
    true
    iex> Enum.all?(cart, & &1.count > 1)
    false

`all?` with an empty collection is always true:

    iex> Enum.all?([], & &1.count > 0)
    true

### `member?(enum, value)`

    iex> Enum.member?(cart, %{fruit: "apple", count: 3})
    true
    iex> Enum.member?(cart, :something_else)
    false

`item in enum` is equivalent to `Enum.member?(enum, item)`:

    iex> %{fruit: "apple", count: 3} in cart
    true
    iex> :something_else in cart
    false

### `empty?(enum)`

    iex> Enum.empty?(cart)
    false
    iex> Enum.empty?([])
    true

## Filtering

### `filter(enum, fun)`

    iex> Enum.filter(cart, &(&1.fruit =~ "o"))
    [%{fruit: "orange", count: 6}]
    iex> Enum.filter(cart, &(&1.fruit =~ "e"))
    [
      %{fruit: "apple", count: 3},
      %{fruit: "orange", count: 6}
    ]

### `reject(enum, fun)`

    iex> Enum.reject(cart, &(&1.fruit =~ "o"))
    [
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1}
    ]

### `Comprehension`

Filtering can also be done with comprehensions:

    iex> for item <- cart, item.fruit =~ "e" do
    ...>   item
    ...> end
    [
      %{fruit: "apple", count: 3},
      %{fruit: "orange", count: 6}
    ]

Pattern-matching in comprehensions acts as a filter as well:

    iex> for %{count: 1, fruit: fruit} <- cart do
    ...>   fruit
    ...> end
    ["banana"]

## Mapping

### `map(enum, fun)`

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

### `map_every(enum, nth, fun)`

    iex> Enum.map_every(cart, 2, fn item ->
    ...>   %{item | count: item.count + 10}
    ...> end)
    [
      %{fruit: "apple", count: 13},
      %{fruit: "banana", count: 1},
      %{fruit: "orange", count: 16}
    ]

### `Comprehension`

Mapping can also be done with comprehensions:

    iex> for item <- cart do
    ...>   item.fruit
    ...> end
    ["apple", "banana", "orange"]

You can also filter and map at once:

    iex> for item <- cart, item.fruit =~ "e" do
    ...>   item.fruit
    ...> end
    ["apple", "orange"]

## Side-effects

### `each(enum, fun)`

    iex> Enum.each(cart, &IO.puts(&1.fruit))
    apple
    banana
    orange
    :ok

`Enum.each/2` is used exclusively for side-effects.

## Accumulating

### `reduce(enum, acc, fun)`

    iex> Enum.reduce(cart, 0, fn item, acc ->
    ...>   item.count + acc
    ...> end)
    10

### `map_reduce(enum, acc, fun)`

    iex> Enum.map_reduce(cart, 0, fn item, acc ->
    ...>   {item.fruit, item.count + acc}
    ...> end)
    {["apple", "banana", "orange"], 10}

### `scan(enum, acc, fun)`

    iex> Enum.scan(cart, 0, fn item, acc ->
    ...>   item.count + acc
    ...> end)
    [3, 4, 10]

### `reduce_while(enum, acc, fun)`

    iex> Enum.reduce_while(cart, 0, fn item, acc ->
    ...>   if item.fruit == "orange" do
    ...>     {:halt, acc}
    ...>   else
    ...>     {:cont, item.count + acc}
    ...>   end
    ...> end)
    4

### `Comprehension`

Reducing can also be done with comprehensions:

    iex> for item <- cart, reduce: 0 do
    ...>   acc -> item.count + acc
    ...> end
    10

You can also filter and reduce at once:

    iex> for item <- cart, item.fruit =~ "e", reduce: 0 do
    ...>   acc -> item.count + acc
    ...> end
    9

## Aggregations

### `count(enum)`

    iex> Enum.count(cart)
    3

See `Enum.count_until/2` to count until a limit.

### `frequencies(enum)`

    iex> Enum.frequencies(["apple", "banana", "orange", "apple"])
    %{"apple" => 2, "banana" => 1, "orange" => 1}

### `frequencies_by(enum, key_fun)`

Frequencies of the last letter of the fruit:

    iex> Enum.frequencies_by(cart, &String.last(&1.fruit))
    %{"a" => 1, "e" => 2}

### `count(enum, fun)`

    iex> Enum.count(cart, &(&1.fruit =~ "e"))
    2
    iex> Enum.count(cart, &(&1.fruit =~ "y"))
    0

See `Enum.count_until/3` to count until a limit with a function.

### `sum(enum)`

    iex> cart |> Enum.map(& &1.count) |> Enum.sum()
    10

### `product(enum)`

    iex> cart |> Enum.map(& &1.count) |> Enum.product()
    18

## Sorting

### `sort(enum, sorter \\ :asc)`

    iex> cart |> Enum.map(& &1.fruit) |> Enum.sort()
    ["apple", "banana", "orange"]
    iex> cart |> Enum.map(& &1.fruit) |> Enum.sort(:desc)
    ["orange", "banana", "apple"]

When sorting structs, use `Enum.sort/2` with a module as sorter.

### `sort_by(enum, mapper, sorter \\ :asc)`

    iex> Enum.sort_by(cart, & &1.count)
    [
      %{fruit: "banana", count: 1},
      %{fruit: "apple", count: 3},
      %{fruit: "orange", count: 6}
    ]
    iex> Enum.sort_by(cart, & &1.count, :desc)
    [
      %{fruit: "orange", count: 6},
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1}
    ]

When the sorted by value is a struct, use `Enum.sort_by/3` with a module as sorter.

### `min(enum)`

    iex> cart |> Enum.map(& &1.count) |> Enum.min()
    1

When comparing structs, use `Enum.min/2` with a module as sorter.

### `min_by(enum, mapper)`

    iex> Enum.min_by(cart, & &1.count)
    %{fruit: "banana", count: 1}

When comparing structs, use `Enum.min_by/3` with a module as sorter.

### `max(enum)`

    iex> cart |> Enum.map(& &1.count) |> Enum.max()
    6

When comparing structs, use `Enum.max/2` with a module as sorter.

### `max_by(enum, mapper)`

    iex> Enum.max_by(cart, & &1.count)
    %{fruit: "orange", count: 6}

When comparing structs, use `Enum.max_by/3` with a module as sorter.

## Concatenating & flattening

### `concat(enums)`

    iex> Enum.concat([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

### `concat(left, right)`

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

### `flat_map(enum, fun)`

    iex> Enum.flat_map(cart, fn item ->
    ...>   List.duplicate(item.fruit, item.count)
    ...> end)
    ["apple", "apple", "apple", "banana", "orange",
     "orange", "orange", "orange", "orange", "orange"]

### `flat_map_reduce(enum, acc, fun)`

    iex> Enum.flat_map_reduce(cart, 0, fn item, acc ->
    ...>   list = List.duplicate(item.fruit, item.count)
    ...>   acc = acc + item.count
    ...>   {list, acc}
    ...> end)
    {["apple", "apple", "apple", "banana", "orange",
      "orange", "orange", "orange", "orange", "orange"], 10}

### `Comprehension`

Flattening can also be done with comprehensions:

    iex> for item <- cart,
    ...>     fruit <- List.duplicate(item.fruit, item.count) do
    ...>   fruit
    ...> end
    ["apple", "apple", "apple", "banana", "orange",
     "orange", "orange", "orange", "orange", "orange"]

## Conversion

### `into(enum, collectable)`

    iex> pairs = [{"apple", 3}, {"banana", 1}, {"orange", 6}]
    iex> Enum.into(pairs, %{})
    %{"apple" => 3, "banana" => 1, "orange" => 6}

### `into(enum, collectable, transform)`

    iex> Enum.into(cart, %{}, fn item ->
    ...>   {item.fruit, item.count}
    ...> end)
    %{"apple" => 3, "banana" => 1, "orange" => 6}

### `to_list(enum)`

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

### `Comprehension`

Conversion can also be done with comprehensions:

    iex> for item <- cart, into: %{} do
    ...>   {item.fruit, item.count}
    ...> end
    %{"apple" => 3, "banana" => 1, "orange" => 6}

## Duplicates & uniques

### `dedup(enum)`

`dedup` only removes contiguous duplicates:

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

### `dedup_by(enum, fun)`

Remove contiguous entries given a property:

    iex> Enum.dedup_by(cart, & &1.fruit =~ "a")
    [%{fruit: "apple", count: 3}]
    iex> Enum.dedup_by(cart, & &1.count < 5)
    [
      %{fruit: "apple", count: 3},
      %{fruit: "orange", count: 6}
    ]

### `uniq(enum)`

`uniq` applies to the whole collection:

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

Comprehensions also support the `uniq: true` option.

### `uniq_by(enum, fun)`

Get entries which are unique by the last letter of the fruit:

    iex> Enum.uniq_by(cart, &String.last(&1.fruit))
    [
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1}
    ]

## Indexing

### `at(enum, index, default \\ nil)`

    iex> Enum.at(cart, 0)
    %{fruit: "apple", count: 3}
    iex> Enum.at(cart, 10)
    nil
    iex> Enum.at(cart, 10, :none)
    :none

Accessing a list by index in a loop is discouraged.

### `fetch(enum, index)`

    iex> Enum.fetch(cart, 0)
    {:ok, %{fruit: "apple", count: 3}}
    iex> Enum.fetch(cart, 10)
    :error

### `fetch!(enum, index)`

    iex> Enum.fetch!(cart, 0)
    %{fruit: "apple", count: 3}
    iex> Enum.fetch!(cart, 10)
    ** (Enum.OutOfBoundsError) out of bounds error

### `with_index(enum)`

    iex> Enum.with_index(cart)
    [
      {%{fruit: "apple", count: 3}, 0},
      {%{fruit: "banana", count: 1}, 1},
      {%{fruit: "orange", count: 6}, 2}
    ]

### `with_index(enum, fun)`

    iex> Enum.with_index(cart, fn item, index ->
    ...>   {item.fruit, index}
    ...> end)
    [
      {"apple", 0},
      {"banana", 1},
      {"orange", 2}
    ]

## Finding

### `find(enum, default \\ nil, fun)`

    iex> Enum.find(cart, &(&1.fruit =~ "o"))
    %{fruit: "orange", count: 6}
    iex> Enum.find(cart, &(&1.fruit =~ "y"))
    nil
    iex> Enum.find(cart, :none, &(&1.fruit =~ "y"))
    :none

### `find_index(enum, fun)`

    iex> Enum.find_index(cart, &(&1.fruit =~ "o"))
    2
    iex> Enum.find_index(cart, &(&1.fruit =~ "y"))
    nil

### `find_value(enum, default \\ nil, fun)`

    iex> Enum.find_value(cart, fn item ->
    ...>   if item.count == 1, do: item.fruit, else: nil
    ...> end)
    "banana"
    iex> Enum.find_value(cart, :none, fn item ->
    ...>   if item.count == 100, do: item.fruit, else: nil
    ...> end)
    :none

## Grouping

### `group_by(enum, key_fun)`

Group by the last letter of the fruit:

    iex> Enum.group_by(cart, &String.last(&1.fruit))
    %{
      "a" => [%{fruit: "banana", count: 1}],
      "e" => [
        %{fruit: "apple", count: 3},
        %{fruit: "orange", count: 6}
      ]
    }

### `group_by(enum, key_fun, value_fun)`

Group by the last letter of the fruit with custom value:

    iex> Enum.group_by(cart, &String.last(&1.fruit), & &1.fruit)
    %{
      "a" => ["banana"],
      "e" => ["apple", "orange"]
    }

## Joining & interspersing

### `join(enum, joiner \\ "")`

    iex> Enum.join(["apple", "banana", "orange"], ", ")
    "apple, banana, orange"

### `map_join(enum, joiner \\ "", mapper)`

    iex> Enum.map_join(cart, ", ", & &1.fruit)
    "apple, banana, orange"

### `intersperse(enum, separator \\ "")`

    iex> Enum.intersperse(["apple", "banana", "orange"], ", ")
    ["apple", ", ", "banana", ", ", "orange"]

### `map_intersperse(enum, separator \\ "", mapper)`

    iex> Enum.map_intersperse(cart, ", ", & &1.fruit)
    ["apple", ", ", "banana", ", ", "orange"]

## Slicing

### `slice(enum, index_range)`

    iex> Enum.slice(cart, 0..1)
    [
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1}
    ]

Negative ranges count from the back:

    iex> Enum.slice(cart, -2..-1)
    [
      %{fruit: "banana", count: 1},
      %{fruit: "orange", count: 6}
    ]

### `slice(enum, start_index, amount)`

    iex> Enum.slice(cart, 1, 2)
    [
      %{fruit: "banana", count: 1},
      %{fruit: "orange", count: 6}
    ]

### `slide(enum, range_or_single_index, insertion_index)`

    fruits = ["apple", "banana", "grape", "orange", "pear"]
    iex> Enum.slide(fruits, 2, 0)
    ["grape", "apple", "banana", "orange", "pear"]
    iex> Enum.slide(fruits, 2, 4)
    ["apple", "banana", "orange", "pear", "grape"]
    iex> Enum.slide(fruits, 1..3, 0)
    ["banana", "grape", "orange", "apple", "pear"]
    iex> Enum.slide(fruits, 1..3, 4)
    ["apple", "pear", "banana", "grape", "orange"]

## Reversing

### `reverse(enum)`

    iex> Enum.reverse(cart)
    [
      %{fruit: "orange", count: 6},
      %{fruit: "banana", count: 1},
      %{fruit: "apple", count: 3}
    ]

### `reverse(enum, tail)`

    iex> Enum.reverse(cart, [:this_will_be, :the_tail])
    [
      %{fruit: "orange", count: 6},
      %{fruit: "banana", count: 1},
      %{fruit: "apple", count: 3},
      :this_will_be,
      :the_tail
    ]

### `reverse_slice(enum, start_index, count)`

    iex> Enum.reverse_slice(cart, 1, 2)
    [
      %{fruit: "apple", count: 3},
      %{fruit: "orange", count: 6},
      %{fruit: "banana", count: 1}
    ]

## Splitting

### `split(enum, amount)`

    iex> Enum.split(cart, 1)
    {[%{fruit: "apple", count: 3}],
     [
       %{fruit: "banana", count: 1},
       %{fruit: "orange", count: 6}
     ]}

Negative indexes count from the back:

    iex> Enum.split(cart, -1)
    {[
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1}
     ],
     [%{fruit: "orange", count: 6}]}

### `split_while(enum, fun)`

Stops splitting as soon as it is false:

    iex> Enum.split_while(cart, &(&1.fruit =~ "e"))
    {[%{fruit: "apple", count: 3}],
     [
       %{fruit: "banana", count: 1},
       %{fruit: "orange", count: 6}
     ]}

### `split_with(enum, fun)`

Splits the whole collection:

    iex> Enum.split_with(cart, &(&1.fruit =~ "e"))
    {[
      %{fruit: "apple", count: 3},
      %{fruit: "orange", count: 6}
     ],
     [%{fruit: "banana", count: 1}]}

## Splitting (drop and take)

### `drop(enum, amount)`

    iex> Enum.drop(cart, 1)
    [
      %{fruit: "banana", count: 1},
      %{fruit: "orange", count: 6}
    ]

Negative indexes count from the back:

    iex> Enum.drop(cart, -1)
    [
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1}
    ]

### `drop_every(enum, nth)`

    iex> Enum.drop_every(cart, 2)
    [%{fruit: "banana", count: 1}]

### `drop_while(enum, fun)`

    iex> Enum.drop_while(cart, &(&1.fruit =~ "e"))
    [
      %{fruit: "banana", count: 1},
      %{fruit: "orange", count: 6}
    ]

### `take(enum, amount)`

    iex> Enum.take(cart, 1)
    [%{fruit: "apple", count: 3}]

Negative indexes count from the back:

    iex> Enum.take(cart, -1)
    [%{fruit: "orange", count: 6}]

### `take_every(enum, nth)`

    iex> Enum.take_every(cart, 2)
    [
      %{fruit: "apple", count: 3},
      %{fruit: "orange", count: 6}
    ]

### `take_while(enum, fun)`

    iex> Enum.take_while(cart, &(&1.fruit =~ "e"))
    [%{fruit: "apple", count: 3}]

## Random

### `random(enum)`

Results will vary on every call:

    iex> Enum.random(cart)
    %{fruit: "orange", count: 6}

### `take_random(enum, count)`

Results will vary on every call:

    iex> Enum.take_random(cart, 2)
    [
      %{fruit: "orange", count: 6},
      %{fruit: "apple", count: 3}
    ]

### `shuffle(enum)`

Results will vary on every call:

    iex> Enum.shuffle(cart)
    [
      %{fruit: "orange", count: 6},
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1}
    ]

## Chunking

### `chunk_by(enum, fun)`

    iex> Enum.chunk_by(cart, &String.length(&1.fruit))
    [
      [%{fruit: "apple", count: 3}],
      [
        %{fruit: "banana", count: 1},
        %{fruit: "orange", count: 6}
      ]
    ]

### `chunk_every(enum, count)`

    iex> Enum.chunk_every(cart, 2)
    [
      [
        %{fruit: "apple", count: 3},
        %{fruit: "banana", count: 1}
      ],
      [%{fruit: "orange", count: 6}]
    ]

### `chunk_every(enum, count, step, leftover \\ [])`

    iex> Enum.chunk_every(cart, 2, 2, [:elements, :to_complete])
    [
      [
        %{fruit: "apple", count: 3},
        %{fruit: "banana", count: 1}
      ],
      [
        %{fruit: "orange", count: 6},
        :elements
      ]
    ]
    iex> Enum.chunk_every(cart, 2, 1, :discard)
    [
      [
        %{fruit: "apple", count: 3},
        %{fruit: "banana", count: 1}
      ],
      [
        %{fruit: "banana", count: 1},
        %{fruit: "orange", count: 6}
      ]
    ]

See `Enum.chunk_while/4` for custom chunking.

## Zipping

### `zip(enum1, enum2)`

    iex> fruits = ["apple", "banana", "orange"]
    iex> counts = [3, 1, 6]
    iex> Enum.zip(fruits, counts)
    [{"apple", 3}, {"banana", 1}, {"orange", 6}]

See `Enum.zip/1` for zipping many collections at once.

### `zip_with(enum1, enum2, fun)`

    iex> fruits = ["apple", "banana", "orange"]
    iex> counts = [3, 1, 6]
    iex> Enum.zip_with(fruits, counts, fn fruit, count ->
    ...>   %{fruit: fruit, count: count}
    ...> end)
    [
      %{fruit: "apple", count: 3},
      %{fruit: "banana", count: 1},
      %{fruit: "orange", count: 6}
    ]

See `Enum.zip_with/2` for zipping many collections at once.

### `zip_reduce(left, right, acc, fun)`

    iex> fruits = ["apple", "banana", "orange"]
    iex> counts = [3, 1, 6]
    iex> Enum.zip_reduce(fruits, counts, 0, fn fruit, count, acc ->
    ...>   price = if fruit =~ "e", do: count * 2, else: count
    ...>   acc + price
    ...> end)
    19

See `Enum.zip_reduce/3` for zipping many collections at once.

### `unzip(list)`

    iex> cart |> Enum.map(&{&1.fruit, &1.count}) |> Enum.unzip()
    {["apple", "banana", "orange"], [3, 1, 6]}

← Previous Page Debugging
Next Page → What are anti-patterns?