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?))

我們還有許多其他函式,但是這裡只描述了一些重要的函式。

廣告