Fork me on GitHub


A set of algorithms for enumerating over collections.

Table of Contents


The Enum module includes nearly 100 functions for working with the collections we learned about in the last lesson.

This lesson will only cover a subset of the available functions, however we can actually examine them ourselves.
Let’s do a little experiment in IEx.

iex> Enum.__info__(:functions) |> Enum.each(fn({function, arity}) ->
...>   IO.puts "#{function}/#{arity}"
...> end)

Using this, its clear that we have a vast amount of functionality, and that is for a clear reason.
Enumeration is at the core of functional programming and is an incredibly useful thing.
By leveraging it combined with other perks of Elixir, such as documentation being a first class citizen as we just saw, it can be incredibly empowering to the developer as well.

For a full list of functions visit the official Enum docs; for lazy enumeration use the Stream module.


When using all?, and much of Enum, we supply a function to apply to our collection’s items. In the case of all?, the entire collection must evaluate to true otherwise false will be returned:

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


Unlike the above, any? will return true if at least one item evaluates to true:

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


If you need to break your collection up into smaller groups, chunk is the function you’re probably looking for:

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

There are a few options for chunk but we won’t go into them, check out chunk/2 in the official docs to learn more.


If we need to group our collection based on something other than size, we can use the chunk_by/2 method. It takes a given enumerable and a function, and when the return on that function changes a new group is started and begins the creation of the next:

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"]]


Sometimes chunking out a collection isn’t enough for exactly what we may need. If this is the case, map_every/3 can be very useful to hit only specific items if your collection has an ordering that such is necessary or useful:

iex> Enum.map_every([1, 2, 3, 4], 2, fn x -> x * 2 end)
[2, 2, 6, 4]


It may be necessary to iterate over a collection without producing a new value, for this case we use each:

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

Note: The each method does return the atom :ok.


To apply our function to each item and produce a new collection look to the map function:

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


min/1 finds the min value in the collection:

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

min/2 does the same, but allows us to specify the calculation that will produce the minimum via an anonymous function:

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


max/1 returns the max value in the collection:

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

max/2 does the same, and behaves as min/2 does as well, allowing us to specify the calculation that will produce the maximum via an anonymous function:

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


With reduce we can distill our collection down into a single value. To do this we supply an optional accumulator (10 in this example) to be passed into our function; if no accumulator is provided the first value is used:

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


Sorting our collections is made easy with not one, but two, sort functions. The first option available to us uses Elixir’s term ordering to determine the sorted order:

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"]

The other option allows us to provide a sort function:

# with our function
iex> Enum.sort([%{:val => 4}, %{:val => 1}], fn(x, y) -> x[:val] > y[:val] end)
[%{val: 4}, %{val: 1}]

# without
iex> Enum.sort([%{:count => 4}, %{:count => 1}])
[%{count: 1}, %{count: 4}]


We can use uniq_by/2 to remove duplicates from our collections:

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

This was previously known as uniq/1, which is deprecated as of Elixir 1.4, but still available (with warnings).

Share This Page