# Enum 模块

Some contents of this translation may be outdated.
Several minor changes were applied to the original lesson since the last update.

## Enum

`Enum` 模块提供了超过70个操作枚举类型的函数。我们在上一节学到的集合类型中除了元组（tuple）之外都是枚举类型。

``````iex
iex> Enum.__info__(:functions) |> Enum.each(fn({function, arity}) ->
...>   IO.puts "#{function}/#{arity}"
...> end)
all?/1
all?/2
any?/1
any?/2
at/2
at/3
...
``````

### all?

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

### any?

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

### chunk_every/2

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

`chunk_every/2` 还有其他选项，在这里不深入介绍。如果感兴趣，前往 `chunk_every/4` 的官方文档去了解。

### chunk_by

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

### map_every

``````# Apply function every three items
iex> Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8], 3, fn x -> x + 1000 end)
[1001, 2, 3, 1004, 5, 6, 1007, 8]
``````

### each

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

### map

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

### min

`min/1` 在集合中找到最小的值：

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

`min/2` 也一样，但是它允许我们提供一个匿名函数指定计算最小值的方法：

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

### max

`max/1` 返回集合中最大的值：

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

`max/2` 也一样，而且像 `min/2` 一样，它允许我们提供一个匿名函数指定计算最大值的方法：

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

### filter

`filter/2` 函数可以帮我们过滤集合，只留下能是我们提供的函数返回`true`的那些元素。

``````iex> Enum.filter([1, 2, 3, 4], fn(x) -> rem(x, 2) == 0 end)
[2, 4]
``````

### reduce

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

### sort

`sort/1` 使用了 Erlang 的 数据比较规则 来决定排序的顺序：

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

``````# 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}]
``````

### uniq

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

### uniq_by

`uniq_by/2` 也可以用来删除集合中的重复元素，只是它允许我们提供自定义的函数来作唯一性比较。

``````iex> Enum.uniq_by([%{x: 1, y: 1}, %{x: 2, y: 1}, %{x: 3, y: 3}], fn coord -> coord.y end)
[%{x: 1, y: 1}, %{x: 3, y: 3}]
``````

### 使用 & 操作符

Enum 模块中的很多函数接收一个 匿名函数 作为参数。

#### 用 & 操作符取代一个匿名函数

``````iex> Enum.map([1,2,3], fn number -> number + 3 end)
[4, 5, 6]
``````

``````iex> Enum.map([1,2,3], &(&1 + 3))
[4, 5, 6]
``````

``````iex> plus_three = &(&1 + 3)
iex> Enum.map([1,2,3], plus_three)
[4, 5, 6]
``````

#### 在具名函数上使用 & 操作符

``````defmodule Adding do
def plus_three(number), do: number + 3
end

iex>  Enum.map([1,2,3], fn number -> Adding.plus_three(number) end)
[4, 5, 6]
``````

``````iex> Enum.map([1,2,3], &Adding.plus_three(&1))
[4, 5, 6]
``````

``````iex> Enum.map([1,2,3], &Adding.plus_three/1)
[4, 5, 6]
``````
Caught a mistake or want to contribute to the lesson? Edit this page on GitHub!