NOTE: Enum.chunks has become Enum.chunk, and Enum.chunks_by has become Enum.chunk_by.

Hello again, and welcome to Episode 017: Enum, Part 1. In today's episode, we're going to cover the first part of the Enum module.

  • all?
  • any?
  • at
  • chunks
  • chunks_by
  • concat
  • count

Let's get started.

all?

Enum.all? returns true unless one or more items in the collection return false for the provided fun:

iex(1)> Enum.all?([1,2,3], fn(x) -> rem(x, 2) == 0 end)
false
iex(2)> Enum.all?([1,2,3], fn(x) -> x > 0 end)
true

any?

Enum.any? returns true if at least one item in the collection returns true for the provided fun:

iex(3)> Enum.any?([1,2,3], fn(x) -> rem(x, 2) == 0 end)
true
iex(4)> Enum.any?([1,2,3], fn(x) -> x < 0 end)
false

at

Enum.at finds the element in the collection at the given index. This is a zero-based index.

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

chunks

Enum.chunks returns chunks of the collection. It has a few different ways of being called. The most simple and understandable is Enum.chunks/2:

iex(10)> Enum.chunks([1,2,3,4], 2)
[[1, 2], [3, 4]]

When called with arity 2 (Enum.chunks(collection, size)), it returns a collection of lists containing size elements each. By default, you're guaranteed to have each item in the list be of size size, but that means you might not get every element from the input collection out of it. For instance:

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

Here, 5 is not returned because there aren't enough items in the list to place it into an appropriately-sized chunk.

When called with arity 3 (Enum.chunks(collection, size, step)), you can define the step between chunks. With arity 2, step is the same as size. Here's an example:

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

The final way you can call it is with arity 4 (Enum.chunks(collection, size, step, padding)). When called this way, items are taken from padding to fill out any gaps to finish up the final chunk:

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

If there aren't enough items in padding then the last chunk is returned without the same size as the rest. Here's an example:

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

chunks_by

Enum.chunks_by splits the input collection at each point where fun returns a new value. I'm basically copying the example from the documentation here, because it does a great job of showing this behaviour in a fairly nuanced way:

iex(19)> Enum.chunks_by([1, 2, 2, 3, 4, 4, 6, 7, 7], fn(x) -> rem(x, 2) == 1 end)
[[1], [2, 2], [3], [4, 4, 6], [7, 7]]

concat

Enum.concat concatenates a list of enumerables into a single list:

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

All of my examples have focused on lists, but Enum works on anything that implements the Enum protocol - for instance, ranges:

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

count

Enum.count/1 returns the number of items in the input collection:

iex(23)> Enum.count([:a, :b])
2

With arity 2, it returns the number of items in the input collection for which the fun returns true:

iex(24)> Enum.count([:a, 1], fn(x) -> is_integer(x) end)
1

Links