- Elixir 教程
- Elixir - 首页
- Elixir - 概述
- Elixir - 环境
- Elixir - 基本语法
- Elixir - 数据类型
- Elixir - 变量
- Elixir - 运算符
- Elixir - 模式匹配
- Elixir - 决策
- Elixir - 字符串
- Elixir - 字符列表
- Elixir - 列表和元组
- Elixir - 关键字列表
- Elixir - 映射
- Elixir - 模块
- Elixir - 别名
- Elixir - 函数
- Elixir - 递归
- Elixir - 循环
- Elixir - 可枚举
- Elixir - 流
- Elixir - 结构体
- Elixir - 协议
- Elixir - 文件 I/O
- Elixir - 进程
- Elixir - 符号
- Elixir - 推导式
- Elixir - 类型规范
- Elixir - 行为
- Elixir - 错误处理
- Elixir - 宏
- Elixir - 库
- Elixir 有用资源
- Elixir - 快速指南
- Elixir - 有用资源
- Elixir - 讨论
Elixir - 可枚举
可枚举对象是可以枚举的对象。“枚举”是指逐一(通常按顺序,通常按名称)计算集合/集合/类别的成员。
Elixir 提供了可枚举的概念以及 Enum 模块 来处理它们。Enum 模块中的函数仅限于(顾名思义)枚举数据结构中的值。可枚举数据结构的示例包括列表、元组、映射等。Enum 模块为我们提供了 100 多个处理枚举的函数。我们将在本章中讨论一些重要的函数。
所有这些函数都将可枚举作为第一个元素,将函数作为第二个元素,并在其上进行操作。这些函数描述如下。
all?
我们何时使用all?函数,整个集合必须计算结果为真,否则将返回假。例如,要检查列表中的所有元素是否都是奇数,则。
res = Enum.all?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end) IO.puts(res)
运行上述程序时,会产生以下结果:
false
这是因为此列表并非所有元素都是奇数。
any?
顾名思义,如果集合的任何元素计算结果为真,则此函数返回真。例如:
res = Enum.any?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end) IO.puts(res)
运行上述程序时,会产生以下结果:
true
chunk
此函数将我们的集合划分为指定为第二个参数的大小的小块。例如:
res = Enum.chunk([1, 2, 3, 4, 5, 6], 2) IO.puts(res)
运行上述程序时,会产生以下结果:
[[1, 2], [3, 4], [5, 6]]
each
可能需要迭代集合而无需生成新值,在这种情况下,我们使用each函数:
Enum.each(["Hello", "Every", "one"], fn(s) -> IO.puts(s) end)
运行上述程序时,会产生以下结果:
Hello Every one
map
要将我们的函数应用于每个项目并生成一个新集合,我们使用 map 函数。它是函数式编程中最有用的构造之一,因为它非常具有表现力和简洁性。让我们考虑一个例子来理解这一点。我们将列表中存储的值加倍,并将其存储在一个新的列表res中:
res = Enum.map([2, 5, 3, 6], fn(a) -> a*2 end) IO.puts(res)
运行上述程序时,会产生以下结果:
[4, 10, 6, 12]
reduce
reduce函数帮助我们将可枚举减少为单个值。为此,我们提供一个可选的累加器(在本例中为 5)传递到我们的函数中;如果未提供累加器,则使用第一个值:
res = Enum.reduce([1, 2, 3, 4], 5, fn(x, accum) -> x + accum end) IO.puts(res)
运行上述程序时,会产生以下结果:
15
累加器是传递给fn的初始值。从第二次调用开始,前一次调用的返回值作为累加器传递。我们也可以在没有累加器的情况下使用 reduce:
res = Enum.reduce([1, 2, 3, 4], fn(x, accum) -> x + accum end) IO.puts(res)
运行上述程序时,会产生以下结果:
10
uniq
uniq 函数从我们的集合中删除重复项,并且仅返回集合中元素的集合。例如:
res = Enum.uniq([1, 2, 2, 3, 3, 3, 4, 4, 4, 4]) IO.puts(res)
运行上述程序时,会产生以下结果:
[1, 2, 3, 4]
急切求值
Enum 模块中的所有函数都是急切的。许多函数期望一个可枚举并返回一个列表。这意味着当使用 Enum 执行多个操作时,每个操作都将生成一个中间列表,直到我们获得结果。让我们考虑以下示例来理解这一点:
odd? = &(rem(&1, 2) != 0) res = 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum IO.puts(res)
运行上述程序时,会产生以下结果:
7500000000
上面的示例有一个操作管道。我们从一个范围开始,然后将范围中的每个元素乘以 3。此第一个操作现在将创建一个包含 100_000 个项目的列表并返回它。然后,我们保留列表中的所有奇数元素,生成一个新列表,现在包含 50_000 个元素,然后我们对所有条目求和。
上面代码片段中使用的|>符号是管道运算符:它只是获取其左侧表达式的输出,并将其作为第一个参数传递给其右侧的函数调用。它类似于 Unix | 运算符。其目的是突出显示一系列函数转换的数据流。
如果没有管道运算符,代码看起来很复杂:
Enum.sum(Enum.filter(Enum.map(1..100_000, &(&1 * 3)), odd?))
我们还有许多其他函数,但是这里只描述了一些重要的函数。