Enum and Stream
Elixir Enum and Stream functions for iterating, mapping, filtering, and reducing collections
The Enum module works on eager collections (lists, maps, ranges, etc.). Stream provides lazy operations that compute only when needed.
Enum — most used functions
Iteration
| Function |
Example |
Result |
Enum.each/2 |
Enum.each([1,2,3], &IO.puts/1) |
:ok (side effect) |
Enum.map/2 |
Enum.map([1,2,3], &(&1 * 2)) |
[2, 4, 6] |
Enum.filter/2 |
Enum.filter(1..5, &rem(&1,2)==0) |
[2, 4] |
Enum.reject/2 |
Enum.reject(1..5, &rem(&1,2)==0) |
[1, 3, 5] |
Enum.reduce/3 |
Enum.reduce([1,2,3], 0, &+/2) |
6 |
Enum.reduce/2 |
Enum.reduce([1,2,3], &+/2) |
6 (first elem is acc) |
Finding & testing
| Function |
Example |
Result |
Enum.find/3 |
Enum.find([1,2,3], &(&1 > 2)) |
3 |
Enum.find_value/3 |
Enum.find_value([1,2,3], &(&1 > 2 && &1)) |
3 |
Enum.any?/2 |
Enum.any?([1,2,3], &(&1 > 2)) |
true |
Enum.all?/2 |
Enum.all?([1,2,3], &(&1 > 0)) |
true |
Enum.member?/2 |
Enum.member?([1,2,3], 2) |
true |
Enum.empty?/1 |
Enum.empty?([]) |
true |
Enum.count/1 |
Enum.count([1,2,3]) |
3 |
Enum.count/2 |
Enum.count([1,2,3], &(&1 > 1)) |
2 |
Sorting & grouping
| Function |
Example |
Result |
Enum.sort/1 |
Enum.sort([3,1,2]) |
[1, 2, 3] |
Enum.sort/2 |
Enum.sort([3,1,2], :desc) |
[3, 2, 1] |
Enum.sort_by/2 |
Enum.sort_by([~D[2023-01-01], ~D[2022-01-01]], & &1) |
sorted by date |
Enum.group_by/2 |
Enum.group_by([1,2,3], &rem(&1,2)) |
%{1 => [1, 3], 0 => [2]} |
Enum.uniq/1 |
Enum.uniq([1,1,2,2,3]) |
[1, 2, 3] |
Enum.uniq_by/2 |
Enum.uniq_by([1,2,3,4], &rem(&1,2)) |
[1, 2] |
Slicing & chunking
| Function |
Example |
Result |
Enum.take/2 |
Enum.take([1,2,3,4,5], 2) |
[1, 2] |
Enum.drop/2 |
Enum.drop([1,2,3,4,5], 2) |
[3, 4, 5] |
Enum.take_while/2 |
Enum.take_while([1,2,3], &(&1 < 3)) |
[1, 2] |
Enum.drop_while/2 |
Enum.drop_while([1,2,3], &(&1 < 3)) |
[3] |
Enum.slice/2 |
Enum.slice([1,2,3,4,5], 1..3) |
[2, 3, 4] |
Enum.chunk_every/2 |
Enum.chunk_every([1,2,3,4,5], 2) |
[[1,2],[3,4],[5]] |
Enum.chunk_by/2 |
Enum.chunk_by([1,1,2,2,1], &(&1)) |
[[1,1],[2,2],[1]] |
Concat & flatten
| Function |
Example |
Result |
Enum.concat/1 |
Enum.concat([[1,2],[3,4]]) |
[1, 2, 3, 4] |
Enum.concat/2 |
Enum.concat([1,2], [3,4]) |
[1, 2, 3, 4] |
Enum.flat_map/2 |
Enum.flat_map([1,2], &[&1, &1*10]) |
[1, 10, 2, 20] |
Conversions
| Function |
Example |
Result |
Enum.to_list/1 |
Enum.to_list(1..3) |
[1, 2, 3] |
Enum.join/2 |
Enum.join([1,2,3], ", ") |
"1, 2, 3" |
Enum.into/2 |
Enum.into([a: 1], %{}) |
%{a: 1} |
Enum.into/3 |
Enum.into([1,2], [], &(&1 * 2)) |
[2, 4] |
Zip & with_index
| Function |
Example |
Result |
Enum.zip/2 |
Enum.zip([:a,:b], [1,2]) |
[{:a, 1}, {:b, 2}] |
Enum.with_index/1 |
Enum.with_index([:a,:b]) |
[{:a, 0}, {:b, 1}] |
Comprehensions
# Basic
for n <- [1, 2, 3], do: n * n # => [1, 4, 9]
# With filter
for n <- 1..10, rem(n, 2) == 0, do: n # => [2, 4, 6, 8, 10]
# With multiple generators
for x <- [1, 2], y <- [:a, :b], do: {x, y}
# => [{1, :a}, {1, :b}, {2, :a}, {2, :b}]
# Into a map
for {k, v} <- %{a: 1, b: 2}, into: %{}, do: {k, v * 2}
# => %{a: 2, b: 4}
# Uniq option
for n <- [1, 1, 2, 2, 3], uniq: true, do: n # => [1, 2, 3]
Stream — lazy operations
Streams evaluate elements only as needed. Use them for large or infinite collections.
# Creating streams
1..1_000_000 |> Stream.map(&(&1 * 2)) |> Stream.filter(&rem(&1, 3) == 0) |> Enum.take(5)
# => [6, 12, 18, 24, 30]
# Stream.cycle — infinite repetition
Stream.cycle([1, 2, 3]) |> Enum.take(7) # => [1, 2, 3, 1, 2, 3, 1]
# Stream.unfold — generate from state
Stream.unfold(1, fn n -> {n, n + 1} end) |> Enum.take(5) # => [1, 2, 3, 4, 5]
# Stream.iterate — infinite sequence
Stream.iterate(1, &(&1 * 2)) |> Enum.take(5) # => [1, 2, 4, 8, 16]
# File lines (lazy)
File.stream!("log.txt") |> Stream.map(&String.trim/1) |> Enum.take(10)
When to use Stream: When working with large collections, infinite sequences, or when you want to chain multiple operations without creating intermediate lists.