The Enum Module

Introduction

The Enum module is your Swiss-army knife for working with collections. Anything a for loop would do in another language (transform, filter, group, sort, add up, pick an element) you do in Elixir with a function from Enum.

The big idea is always the same: Enum takes a collection and a small function that describes what to do with each element, and gives you back a new collection or a single value.

Consider this example of using Enum to multiply each element in a list by 2:

list = [1, 2, 3, 4]
Enum.map(list, fn x -> x * 2 end)
# => [2, 4, 6, 8]

The Enum.map function takes two arguments: the enumerable (list in this case) and a transformation function for each element.

For further enhancement, Elixir’s pipe operator (|>) can be used with Enum functions for cleaner and more readable code. Here’s an example:

list = [1, 2, 3, 4]
list
  |> Enum.map(fn x -> x * 3 end)
  |> Enum.filter(fn x -> rem(x, 2) == 0 end)
# => [6, 12]

This statement takes a list, multiplies each element by 3 using Enum.map, and then filters out the odd numbers using Enum.filter. The use of the pipe operator makes the code flow naturally and easier to read.

You can also use the &1 shorthand for anonymous functions (see Capture Operator) to increase code readability. Here’s the previous example using the shorthand:

list = [1, 2, 3, 4]
list
  |> Enum.map(&(&1 * 3))
  |> Enum.filter(&rem(&1, 2) == 0)
# => [6, 12]
Enum functions are eager; they execute immediately and return a result. If memory usage is a concern with very large collections, consider using the Stream module for lazy computation.

Commonly Used Enum Functions

Enum offers a ton of useful functions. All are listed at the official Enum documentation. Here are some of the most commonly used functions to give you an idea of what’s available.

Enum.map/2

The Enum.map/2 function is used to transform each element in an enumerable using a provided function.

list = [1, 2, 3, 4]
Enum.map(list, fn x -> x * 2 end)
# => [2, 4, 6, 8]

The &1 shorthand can be used as follows:

list = [1, 2, 3, 4]
list |> Enum.map(&(&1 * 2))
# => [2, 4, 6, 8]

More details can be found at the official Elixir Enum.map/2 documentation.

Enum.filter/2

The Enum.filter/2 function filters out elements based on a provided function.

list = [1, nil, 2, nil, 3]
Enum.filter(list, fn x -> x != nil end)
# => [1, 2, 3]

Using the &1 shorthand:

list = [1, nil, 2, nil, 3]
list |> Enum.filter(&(&1 != nil))
# => [1, 2, 3]

More details can be found at the official Elixir Enum.filter/2 documentation.

Enum.reduce/2,3

The Enum.reduce/2,3 function reduces an enumerable to a single value.

list = [1, 2, 3, 4]
Enum.reduce(list, 0, fn x, acc -> x + acc end)
# => 10
The use of reduce/3 and it’s accumulator is similar to the fold function in other languages. It can be tricky to use.

More details can be found at the official Elixir Enum.reduce/2 documentation.

Enum.sort/1,2

The Enum.sort/1,2 function sorts the elements in an enumerable.

list = [4, 2, 3, 1]
Enum.sort(list)
# => [1, 2, 3, 4]

You can provide a comparator function:

list = [4, 2, 3, 1]
Enum.sort(list, fn a, b -> a > b end)
# => [4, 3, 2, 1]

More details can be found at the official Elixir Enum.sort/2 documentation.

Enum.at/2,3

Returns the element at the given index (zero based) or a default value.

list = [1, 2, 3, 4]
Enum.at(list, 2)
# Output: 3

More details can be found at the official Elixir Enum.at/2,3 documentation.

Enum.concat/1,2

Concatenates the collection of enumerable(s) given.

Enum.concat([[1, 2], [3, 4]])
# Output: [1, 2, 3, 4]

More details can be found at the official Elixir Enum.concat/1,2 documentation.

Enum.count/1,2

Counts the enumerable items, optionally, using the provided function.

list = [1, 2, 3, 4]
Enum.count(list)
# Output: 4

More details can be found at the official Elixir Enum.count/1,2 documentation.

Enum.find/2,3

Finds the first element for which the provided function returns a truthy value.

list = [1, 2, 3, 4]
Enum.find(list, fn x -> x > 2 end)
# Output: 3

More details can be found at the official Elixir Enum.find/2,3 documentation.

Enum.group_by/2,3

Groups all items in the enumerable by the given function.

list = [{:apple, "fruit"}, {:carrot, "vegetable"}, {:banana, "fruit"}]
Enum.group_by(list, fn {_name, type} -> type end)
# %{
#   "fruit" => [apple: "fruit", banana: "fruit"],
#   "vegetable" => [carrot: "vegetable"]
# }
IEx prints {:apple, "fruit"} as apple: "fruit" when every element in the list is a two-tuple starting with an atom, that is just the keyword list syntax. The data is still a list of tuples, the display is nicer to read.

More details can be found at the official Elixir Enum.group_by/2,3 documentation.

Enum.join/1,2

Joins all the items in the enumerable into a single string.

list = ["Hello", "World"]
Enum.join(list, " ")
# Output: "Hello World"

More details can be found at the official Elixir Enum.join/1,2 documentation.

Enum.max/1

Returns the maximum value in the enumerable.

list = [1, 2, 3, 4]
Enum.max(list)
# Output: 4

More details can be found at the official Elixir Enum.max/1 documentation.

Enum.min/1

Returns the minimum value in the enumerable.

list = [1, 2, 3, 4]
Enum.min(list)
# Output: 1

More details can be found at the official Elixir Enum.min/1 documentation.

Enum.random/1

Selects a random element from the enumerable.

list = [1, 2, 3, 4]
Enum.random(list)
# Output: Random value from the list

More details can be found at the official Elixir Enum.random/1 documentation.

Enum.reject/2

Filters out the items in the enumerable for which the provided function returns a truthy value.

list = [1, 2, 3, 4]
Enum.reject(list, fn x -> x < 3 end)
# Output: [3, 4]

More details can be found at the official Elixir Enum.reject/2 documentation.

Enum.sum/1

Returns the sum of all items in the enumerable.

list = [1, 2, 3, 4]
Enum.sum(list)
# Output: 10

More details can be found at the official Elixir Enum.sum/1 documentation.