📜  Elixir-可枚举

📅  最后修改于: 2020-11-04 08:27:23             🧑  作者: Mango


 

可枚举是可以枚举的对象。 “枚举”是指将集合/集合/类别的成员一个个地计数(通常是按顺序,通常是按名称)。

Elixir提供了可枚举的概念以及与之配合使用的Enum模块。顾名思义,Enum模块中的功能仅限于枚举数据结构中的值。可枚举数据结构的示例是列表,元组,映射等。Enum模块为我们提供了100多个处理枚举的函数。我们将在本章中讨论一些重要的功能。

所有这些功能都将枚举作为第一个元素,将函数作为第二个元素并对其进行处理。功能说明如下。

所有?

什么时候使用全部? 函数,整个集合必须评估为true,否则将返回false。例如,要检查列表中的所有元素是否都是奇数。

res = Enum.all?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end) 
IO.puts(res)

运行上述程序时,将产生以下结果-

false

这是因为该列表中的所有元素都不都是奇数。

任何?

顾名思义,如果集合中的任何元素的值为true,则此函数返回true。例如-

res = Enum.any?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end)
IO.puts(res)

运行上述程序时,将产生以下结果-

true

大块

此函数将我们的集合分成第二个参数提供的小块。例如-

res = Enum.chunk([1, 2, 3, 4, 5, 6], 2)
IO.puts(res)

运行上述程序时,将产生以下结果-

[[1, 2], [3, 4], [5, 6]]

可能有必要遍历一个集合而不产生新值,在这种情况下,我们使用each函数-

Enum.each(["Hello", "Every", "one"], fn(s) -> IO.puts(s) end)

运行上述程序时,将产生以下结果-

Hello
Every
one

地图

为了将我们的函数应用于每个项目并产生一个新的集合,我们使用map函数。它是函数式编程中最有用的结构之一,因为它表达性强且简短。让我们考虑一个例子来理解这一点。我们将存储在列表中的值加倍,并将其存储在新列表中res-

res = Enum.map([2, 5, 3, 6], fn(a) -> a*2 end)
IO.puts(res)

运行上述程序时,将产生以下结果-

[4, 10, 6, 12]

减少

减少函数可帮助我们将可枚举减少为单个值。为此,我们提供了一个可选的累加器(在本示例中为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函数从我们的集合中删除重复项,并仅返回集合中的元素集。例如-

res = Enum.uniq([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
IO.puts(res)

当运行上述程序时,它产生以下结果-

[1, 2, 3, 4]

渴望评估

枚举模块中的所有功能都非常渴望。许多函数都要求可枚举并返回列表。这意味着,当对Enum执行多个操作时,每个操作都会生成一个中间列表,直到我们得到结果为止。让我们考虑以下示例以了解这一点-

odd? = &(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?))

我们还有许多其他功能,但是这里仅描述了一些重要的功能。