檢視原始碼 Enum (Elixir v1.16.2)

處理集合(稱為可列舉)的函式。

在 Elixir 中,可列舉是實作 Enumerable 協定的任何資料類型。 List ([1, 2, 3])、Map (%{foo: 1, bar: 2}) 和 Range (1..3) 是用作可列舉的常見資料類型

iex> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]

iex> Enum.sum([1, 2, 3])
6

iex> Enum.map(1..3, fn x -> x * 2 end)
[2, 4, 6]

iex> Enum.sum(1..3)
6

iex> map = %{"a" => 1, "b" => 2}
iex> Enum.map(map, fn {k, v} -> {k, v * 2} end)
[{"a", 2}, {"b", 4}]

語言中還有許多其他可列舉,例如 MapSetFile.stream!/3 傳回的資料類型,它允許將檔案視為可列舉來遍歷。

若要大致瞭解 Enum 模組中的所有函式,請參閱 Enum 參考手冊

此模組中的函式以線性時間運作。這表示執行作業所需的時間會隨著可列舉長度以相同的速率成長。這在 Enum.map/2 等作業中是預期的。畢竟,如果我們要遍歷清單中的每個元素,清單越長,我們需要遍歷的元素就越多,而且所需時間也會越長。

這種線性行為也應出現在類似操作中,例如 count/1member?/2at/2 等。雖然 Elixir 允許資料類型為此類操作提供效能變異,但您不應期望它總是可用,因為 Enum 模組旨在與各種資料類型搭配使用,而且並非所有資料類型都能提供最佳化行為。

最後,請注意 Enum 模組中的函式是急切的:它們會在呼叫後立即遍歷可列舉物件。在使用無限可列舉物件時,這特別危險。在這種情況下,您應使用 Stream 模組,它允許您以延遲方式表達運算,而無需遍歷集合,並使用可能無限的集合。請參閱 Stream 模組以取得範例和文件。

摘要

類型

從 0 開始的索引。它也可以是負整數。

t()

函式

如果 enumerable 中的所有元素都為真,則傳回 true

如果 enumerable 中的所有元素的 fun.(element) 為真,則傳回 true

如果 enumerable 中至少有一個元素為真,則傳回 true

如果 enumerable 中至少有一個元素的 fun.(element) 為真,則傳回 true

尋找給定 index (從 0 開始) 的元素。

fun 傳回新值的每個元素上分割可列舉物件。

簡寫為 chunk_every(enumerable, count, count)

傳回包含 count 個元素的清單清單,其中每個新區塊在 enumerable 中的 step 個元素後開始。

以細緻的控制區塊大小來區塊化 可列舉,並在每個區塊發出時控制。

給定一個可列舉的可列舉,將 可列舉 串接成一個單一清單。

右邊 的可列舉與 左邊 的可列舉串接。

傳回 可列舉 的大小。

傳回 可列舉fun 傳回真值元素的數量。

計算可列舉的數量,在 極限 處停止。

計算可列舉中 fun 傳回真值元素的數量,在 極限 處停止。

列舉 可列舉,傳回一個清單,其中所有連續重複的元素都壓縮成一個單一元素。

列舉 可列舉,傳回一個清單,其中所有連續重複的元素都壓縮成一個單一元素。

可列舉 中移除 數量 的元素。

傳回一個清單,其中 可列舉 中的每個 第 n 個 元素都被移除,從第一個元素開始。

移除 可列舉 開頭的元素,直到 fun 傳回真值。

可列舉 中的每個元素呼叫指定的 fun

判斷 可列舉 是否為空。

尋找給定 index (從 0 開始) 的元素。

尋找給定 index (從 0 開始) 的元素。

過濾 可列舉,亦即只傳回 fun 傳回真值元素。

傳回第一個 fun 傳回真值的元素。如果找不到此類元素,則傳回 預設

類似於 find/3,但傳回元素的索引(從 0 開始),而不是元素本身。

類似於 find/3,但傳回函式呼叫的值,而不是元素本身。

將給定的 funenumerable 進行對應,並將結果扁平化。

enumerable 進行對應和簡化,將給定的結果扁平化(僅一層深度)。

傳回一個映射,其中鍵是 enumerable 的唯一元素,而值是每個元素的計數。

傳回一個映射,其中鍵是 key_fun 給出的唯一元素,而值是每個元素的計數。

根據 key_funenumerable 分割成群組。

在列舉的每個元素之間插入 separator

將給定的 enumerable 插入 collectable 中。

根據轉換函數將給定的 enumerable 插入 collectable 中。

使用 joiner 作為分隔符,將給定的 enumerable 加入成一個字串。

傳回一個清單,其中每個元素都是對 enumerable 的每個對應元素呼叫 fun 的結果。

傳回一個清單,其中結果是對 enumerable 的每個 nth 元素(從第一個元素開始)呼叫 fun 的結果。

一次對應和插入給定的列舉。

一次對應和加入給定的 enumerable

呼叫給定的函數對 enumerable 中的每個元素,以將其簡化為單一元素,同時保留累加器。

根據 Erlang 的術語排序傳回 enumerable 中的最大元素。

傳回 enumerable 中由給定的 fun 計算出的最大元素。

檢查 元素 是否存在於 可列舉 中。

根據 Erlang 項順序,傳回 可列舉 中的最小元素。

根據指定的 fun 計算,傳回 可列舉 中的最小元素。

根據 Erlang 項順序,傳回一個包含可列舉中最小和最大元素的元組。

根據指定的函數計算,傳回一個包含可列舉中最小和最大元素的元組。

傳回所有元素的乘積。

傳回 可列舉 中的隨機元素。

使用累加器,針對 可列舉 中的每個元素呼叫 fun

使用累加器,針對 可列舉 中的每個元素呼叫 fun

縮減 可列舉,直到 fun 傳回 {:halt, 項}

傳回 可列舉 中元素的清單,排除函數 fun 傳回真值的元素。

傳回 可列舉 中元素的清單,順序相反。

反轉 可列舉 中的元素,附加 ,並以清單的形式傳回。

反轉 可列舉 中從初始 起始索引計數 個元素的範圍。

將給定的函式套用至 enumerable 中的每個元素,將結果儲存在清單中,並將其作為下一次運算的累加器傳遞。使用 enumerable 中的第一個元素作為起始值。

將給定的函式套用至 enumerable 中的每個元素,將結果儲存在清單中,並將其作為下一次運算的累加器傳遞。使用給定的 acc 作為起始值。

傳回一個清單,其中包含 enumerable 的元素,且順序已洗牌。

根據 index_range 傳回給定 enumerable 的子集清單。

傳回給定 enumerable 的子集清單,從 start_index (以 0 為基準) 開始,包含 amount 個元素(如果有的話)。

range_or_single_index 給定的單一或多個元素從 enumerable 滑動到 insertion_index

根據 Erlang 的術語排序對 enumerable 進行排序。

根據給定的函式對 enumerable 進行排序。

根據提供的 sorter 函式對 enumerable 的對應結果進行排序。

enumerable 分割成兩個 enumerable,在第一個中保留 count 個元素。

fun 首次對元素傳回假值 (falsenil) 的位置,將 enumerable 分割成兩個。

根據給定的函式 funenumerable 分割成兩個清單。

傳回所有元素的總和。

列舉的開始或結束處取出數量的元素。

列舉中的第一個元素開始,傳回第n個元素的清單。

列舉中取出計數個隨機元素。

列舉的開始處取出元素,同時函數傳回真值。

列舉轉換為清單。

列舉列舉,移除所有重複的元素。

列舉列舉,移除函數函數傳回重複元素的元素。

zip/2的反義詞。從給定的列舉中萃取二元組,並將它們分組在一起。

傳回列舉,每個元素都封裝在一個元組中,並附帶其索引。

將有限集合中對應的列舉元素壓縮成元組清單。

將兩個列舉中對應的元素壓縮成元組清單。

縮減所有給定的列舉,只要任何列舉為空就停止。

縮減兩個列舉,只要任何列舉為空就停止。

將有限集合中對應的列舉元素壓縮成清單,並在過程中使用zip_函數函數轉換它們。

將兩個列舉中對應的元素壓縮成清單,並在過程中使用zip_函數函數轉換它們。

類型

@type acc() :: any()
@type default() :: any()
@type element() :: any()
@type index() :: integer()

從 0 開始的索引。它也可以是負整數。

@type t() :: Enumerable.t()

函數

@spec all?(t()) :: boolean()

如果 enumerable 中的所有元素都為真,則傳回 true

當一個元素具有假值(falsenil)時,迭代會立即停止,並傳回 false。在所有其他情況下,會傳回 true

範例

iex> Enum.all?([1, 2, 3])
true

iex> Enum.all?([1, nil, 3])
false

iex> Enum.all?([])
true
@spec all?(t(), (element() -> as_boolean(term()))) :: boolean()

如果 enumerable 中的所有元素的 fun.(element) 為真,則傳回 true

迭代 enumerable 並在每個元素上呼叫 fun。如果 fun 曾經傳回假值(falsenil),迭代會立即停止,並傳回 false。否則,會傳回 true

範例

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

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

iex> Enum.all?([], fn _ -> nil end)
true

如同最後一個範例所示,Enum.all?/2 會傳回 true,如果 enumerable 為空,不論 fun 為何。在一個空的列舉中,沒有任何元素會讓 fun 傳回假值,所以結果必定是 true。這是一個定義良好的邏輯論證,適用於空集合。

@spec any?(t()) :: boolean()

如果 enumerable 中至少有一個元素為真,則傳回 true

當一個元素具有真值(既不是 false 也不是 nil)時,迭代會立即停止,並傳回 true。在所有其他情況下,會傳回 false

範例

iex> Enum.any?([false, false, false])
false

iex> Enum.any?([false, true, false])
true

iex> Enum.any?([])
false
@spec any?(t(), (element() -> as_boolean(term()))) :: boolean()

如果 enumerable 中至少有一個元素的 fun.(element) 為真,則傳回 true

迭代 enumerable 並在每個元素上呼叫 fun。當呼叫 fun 傳回真值(既不是 false 也不是 nil)時,迭代會立即停止,並傳回 true。在所有其他情況下,會傳回 false

範例

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

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

iex> Enum.any?([], fn x -> x > 0 end)
false
連結至這個函式

at(enumerable, index, default \\ nil)

檢視來源
@spec at(t(), index(), default()) :: element() | default()

尋找給定 index (從 0 開始) 的元素。

如果 index 超出範圍,傳回 default

可以傳入負的 index,這表示 enumerable 會列舉一次,而 index 會從結尾開始計算(例如,-1 會找到最後一個元素)。

範例

iex> Enum.at([2, 4, 6], 0)
2

iex> Enum.at([2, 4, 6], 2)
6

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

iex> Enum.at([2, 4, 6], 4, :none)
:none
連結至這個函式

chunk_by(enumerable, fun)

檢視來源
@spec chunk_by(t(), (element() -> any())) :: [list()]

fun 傳回新值的每個元素上分割可列舉物件。

傳回一個列表的列表。

範例

iex> Enum.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1))
[[1], [2, 2], [3], [4, 4, 6], [7, 7]]
連結至這個函式

chunk_every(enumerable, count)

檢視原始碼 (自 1.5.0 起)
@spec chunk_every(t(), pos_integer()) :: [list()]

簡寫為 chunk_every(enumerable, count, count)

連結至這個函式

chunk_every(enumerable, count, step, leftover \\ [])

檢視原始碼 (自 1.5.0 起)
@spec chunk_every(t(), pos_integer(), pos_integer(), t() | :discard) :: [list()]

傳回包含 count 個元素的清單清單,其中每個新區塊在 enumerable 中的 step 個元素後開始。

step 為選用參數,若未傳遞,預設為 count,亦即區塊不會重疊。當集合結束或我們發出不完整的區塊時,區塊化將停止。

如果最後一個區塊沒有 count 個元素來填滿區塊,將從 leftover 取用元素來填入區塊。如果 leftover 沒有足夠的元素來填滿區塊,則傳回一個小於 count 個元素的部分區塊。

如果在 leftover 中給定 :discard,則最後一個區塊將被捨棄,除非它剛好有 count 個元素。

範例

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

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

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

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

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

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

iex> Enum.chunk_every([1, 2, 3, 4], 3, 3, Stream.cycle([0]))
[[1, 2, 3], [4, 0, 0]]
連結至這個函式

chunk_while(enumerable, acc, chunk_fun, after_fun)

檢視原始碼 (自 1.5.0 起)
@spec chunk_while(
  t(),
  acc(),
  (element(), acc() -> {:cont, chunk, acc()} | {:cont, acc()} | {:halt, acc()}),
  (acc() -> {:cont, chunk, acc()} | {:cont, acc()})
) :: Enumerable.t()
when chunk: any()

以細緻的控制區塊大小來區塊化 可列舉,並在每個區塊發出時控制。

chunk_fun 接收目前的元素和累加器,且必須傳回

  • {:cont, chunk, acc} 來發出一個區塊並繼續使用累加器
  • {:cont, acc} 來不發出任何區塊並繼續使用累加器
  • {:halt, acc} 來停止在 enumerable 上的區塊化。

after_fun 在反覆運算完成時(或 halt)以最後的累加器呼叫,以處理任何作為累加器一部份傳回的尾隨元素,但未由 chunk_fun 作為區塊發出。它必須傳回

  • {:cont, chunk, acc} 來發出一個區塊。區塊將附加到已發出的區塊列表中。
  • {:cont, acc} 來不發出一個區塊

after_fun 中的 acc 是必需的,以便反映 chunk_fun 的元組格式,但由於遍歷已完成,因此它將被捨棄。

傳回一個已發出區塊的列表。

範例

iex> chunk_fun = fn element, acc ->
...>   if rem(element, 2) == 0 do
...>     {:cont, Enum.reverse([element | acc]), []}
...>   else
...>     {:cont, [element | acc]}
...>   end
...> end
iex> after_fun = fn
...>   [] -> {:cont, []}
...>   acc -> {:cont, Enum.reverse(acc), []}
...> end
iex> Enum.chunk_while(1..10, [], chunk_fun, after_fun)
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
iex> Enum.chunk_while([1, 2, 3, 5, 7], [], chunk_fun, after_fun)
[[1, 2], [3, 5, 7]]
@spec concat(t()) :: t()

給定一個可列舉的可列舉,將 可列舉 串接成一個單一清單。

範例

iex> Enum.concat([1..3, 4..6, 7..9])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

iex> Enum.concat([[1, [2], 3], [4], [5, 6]])
[1, [2], 3, 4, 5, 6]
@spec concat(t(), t()) :: t()

右邊 的可列舉與 左邊 的可列舉串接。

此函數產生與清單的 ++/2 算子相同的結果。

範例

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

iex> Enum.concat([1, 2, 3], [4, 5, 6])
[1, 2, 3, 4, 5, 6]
@spec count(t()) :: non_neg_integer()

傳回 可列舉 的大小。

範例

iex> Enum.count([1, 2, 3])
3
@spec count(t(), (element() -> as_boolean(term()))) :: non_neg_integer()

傳回 可列舉fun 傳回真值元素的數量。

範例

iex> Enum.count([1, 2, 3, 4, 5], fn x -> rem(x, 2) == 0 end)
2
連結至這個函式

count_until(可列舉, 極限)

檢視原始碼 (自 1.12.0 起)
@spec count_until(t(), pos_integer()) :: non_neg_integer()

計算可列舉的數量,在 極限 處停止。

這對於檢查可列舉項目的計數的特定屬性很有用,而無需實際計數整個可列舉項目。例如,如果你想檢查計數是否正好等於、至少等於或大於某個值。

如果可列舉項目實作 Enumerable.count/1,則不會遍歷可列舉項目,而且我們會傳回兩個數字中較小的數字。若要強制列舉,請使用 count_until/3,並將 fn _ -> true end 作為第二個引數。

範例

iex> Enum.count_until(1..20, 5)
5
iex> Enum.count_until(1..20, 50)
20
iex> Enum.count_until(1..10, 10) == 10 # At least 10
true
iex> Enum.count_until(1..11, 10 + 1) > 10 # More than 10
true
iex> Enum.count_until(1..5, 10) < 10 # Less than 10
true
iex> Enum.count_until(1..10, 10 + 1) == 10 # Exactly ten
true
連結至這個函式

count_until(可列舉, fun, 極限)

檢視原始碼 (自 1.12.0 起)
@spec count_until(t(), (element() -> as_boolean(term())), pos_integer()) ::
  non_neg_integer()

計算可列舉中 fun 傳回真值元素的數量,在 極限 處停止。

請參閱 count/2count_until/2 以取得更多資訊。

範例

iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 7)
7
iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 11)
10
@spec dedup(t()) :: list()

列舉 可列舉,傳回一個清單,其中所有連續重複的元素都壓縮成一個單一元素。

元素使用 ===/2 進行比較。

如果你想移除所有重複的元素,不論順序為何,請參閱 uniq/1

範例

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

iex> Enum.dedup([1, 1, 2, 2.0, :three, :three])
[1, 2, 2.0, :three]
@spec dedup_by(t(), (element() -> term())) :: list()

列舉 可列舉,傳回一個清單,其中所有連續重複的元素都壓縮成一個單一元素。

函數 fun 將每個元素對應到一個用於判斷兩個元素是否重複的術語。

範例

iex> Enum.dedup_by([{1, :a}, {2, :b}, {2, :c}, {1, :a}], fn {x, _} -> x end)
[{1, :a}, {2, :b}, {1, :a}]

iex> Enum.dedup_by([5, 1, 2, 3, 2, 1], fn x -> x > 2 end)
[5, 1, 3, 2]
@spec drop(t(), integer()) :: list()

可列舉 中移除 數量 的元素。

如果給定負數 amount,將捨棄最後 amount 個值。將列舉 enumerable 一次以取得適當的索引,並從最後執行其餘的計算。

範例

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

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

iex> Enum.drop([1, 2, 3], 0)
[1, 2, 3]

iex> Enum.drop([1, 2, 3], -1)
[1, 2]
連結至這個函式

drop_every(可列舉, 第 n 個)

檢視來源
@spec drop_every(t(), non_neg_integer()) :: list()

傳回一個清單,其中 可列舉 中的每個 第 n 個 元素都被移除,從第一個元素開始。

第一個元素總是會被捨棄,除非 nth 為 0。

指定每 nth 個元素的第二個參數必須是非負整數。

範例

iex> Enum.drop_every(1..10, 2)
[2, 4, 6, 8, 10]

iex> Enum.drop_every(1..10, 0)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

iex> Enum.drop_every([1, 2, 3], 1)
[]
連結至這個函式

drop_while(可列舉, fun)

檢視來源
@spec drop_while(t(), (element() -> as_boolean(term()))) :: list()

移除 可列舉 開頭的元素,直到 fun 傳回真值。

範例

iex> Enum.drop_while([1, 2, 3, 2, 1], fn x -> x < 3 end)
[3, 2, 1]
@spec each(t(), (element() -> any())) :: :ok

可列舉 中的每個元素呼叫指定的 fun

傳回 :ok

範例

Enum.each(["some", "example"], fn x -> IO.puts(x) end)
"some"
"example"
#=> :ok
@spec empty?(t()) :: boolean()

判斷 可列舉 是否為空。

如果 enumerable 為空,傳回 true,否則傳回 false

範例

iex> Enum.empty?([])
true

iex> Enum.empty?([1, 2, 3])
false
@spec fetch(t(), index()) :: {:ok, element()} | :error

尋找給定 index (從 0 開始) 的元素。

如果找到,傳回 {:ok, element},否則傳回 :error

可以傳入負數 index,表示 enumerable 被列舉一次,而 index 從最後開始計算(例如,-1 會擷取最後一個元素)。

範例

iex> Enum.fetch([2, 4, 6], 0)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], -3)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], 2)
{:ok, 6}

iex> Enum.fetch([2, 4, 6], 4)
:error
連結至這個函式

fetch!(可列舉, 索引)

檢視來源
@spec fetch!(t(), index()) :: element()

尋找給定 index (從 0 開始) 的元素。

如果給定的 index 超出 enumerable 的範圍,會引發 OutOfBoundsError

範例

iex> Enum.fetch!([2, 4, 6], 0)
2

iex> Enum.fetch!([2, 4, 6], 2)
6

iex> Enum.fetch!([2, 4, 6], 4)
** (Enum.OutOfBoundsError) out of bounds error
@spec filter(t(), (element() -> as_boolean(term()))) :: list()

過濾 可列舉,亦即只傳回 fun 傳回真值元素。

另請參閱 reject/2,它會捨棄函數傳回真值的所有元素。

範例

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

請記住,filter 無法同時過濾和轉換元素。如果您想這麼做,請考慮使用 flat_map/2。例如,如果您想轉換所有表示整數的字串,並在一次傳遞中捨棄無效的字串

strings = ["1234", "abc", "12ab"]

Enum.flat_map(strings, fn string ->
  case Integer.parse(string) do
    # transform to integer
    {int, _rest} -> [int]
    # skip the value
    :error -> []
  end
end)
連結至這個函式

find(可列舉, 預設 \\ nil, fun)

檢視來源
@spec find(t(), default(), (element() -> any())) :: element() | default()

傳回第一個 fun 傳回真值的元素。如果找不到此類元素,則傳回 預設

範例

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

iex> Enum.find([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil
iex> Enum.find([2, 4, 6], 0, fn x -> rem(x, 2) == 1 end)
0
連結至這個函式

find_index(可列舉, fun)

檢視來源
@spec find_index(t(), (element() -> any())) :: non_neg_integer() | nil

類似於 find/3,但傳回元素的索引(從 0 開始),而不是元素本身。

範例

iex> Enum.find_index([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

iex> Enum.find_index([2, 3, 4], fn x -> rem(x, 2) == 1 end)
1
連結至這個函式

find_value(可列舉, 預設 \\ nil, fun)

檢視來源
@spec find_value(t(), default(), (element() -> found_value)) ::
  found_value | default()
when found_value: term()

類似於 find/3,但傳回函式呼叫的值,而不是元素本身。

當結果為真值(既不是 nil 也不是 false)時,回傳值會被視為已找到。

範例

iex> Enum.find_value([2, 3, 4], fn x ->
...>   if x > 2, do: x * x
...> end)
9

iex> Enum.find_value([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

iex> Enum.find_value([2, 3, 4], fn x -> rem(x, 2) == 1 end)
true

iex> Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1)
"no bools!"
@spec flat_map(t(), (element() -> t())) :: list()

將給定的 funenumerable 進行對應,並將結果扁平化。

這個函式會回傳一個新的列舉,其建立方式為將呼叫 fun 的結果附加在 enumerable 的每個元素上;從概念上來說,這類似於 map/2concat/1 的組合。

範例

iex> Enum.flat_map([:a, :b, :c], fn x -> [x, x] end)
[:a, :a, :b, :b, :c, :c]

iex> Enum.flat_map([{1, 3}, {4, 6}], fn {x, y} -> x..y end)
[1, 2, 3, 4, 5, 6]

iex> Enum.flat_map([:a, :b, :c], fn x -> [[x]] end)
[[:a], [:b], [:c]]
連結至這個函式

flat_map_reduce(enumerable, acc, fun)

檢視來源
@spec flat_map_reduce(t(), acc(), fun) :: {[any()], acc()}
when fun: (element(), acc() -> {t(), acc()} | {:halt, acc()})

enumerable 進行對應和簡化,將給定的結果扁平化(僅一層深度)。

它預期一個累加器和一個接收每個列舉元素的函式,且必須回傳一個包含一個新列舉(通常為清單)的元組,其中包含新的累加器,或一個元組,其中第一個元素為 :halt,第二個元素為累加器。

範例

iex> enumerable = 1..100
iex> n = 3
iex> Enum.flat_map_reduce(enumerable, 0, fn x, acc ->
...>   if acc < n, do: {[x], acc + 1}, else: {:halt, acc}
...> end)
{[1, 2, 3], 3}

iex> Enum.flat_map_reduce(1..5, 0, fn x, acc -> {[[x]], acc + x} end)
{[[1], [2], [3], [4], [5]], 15}
連結至這個函式

frequencies(enumerable)

檢視原始碼 (自 1.10.0 起)
@spec frequencies(t()) :: map()

傳回一個映射,其中鍵是 enumerable 的唯一元素,而值是每個元素的計數。

範例

iex> Enum.frequencies(~w{ant buffalo ant ant buffalo dingo})
%{"ant" => 3, "buffalo" => 2, "dingo" => 1}
連結至這個函式

frequencies_by(enumerable, key_fun)

檢視原始碼 (自 1.10.0 起)
@spec frequencies_by(t(), (element() -> any())) :: map()

傳回一個映射,其中鍵是 key_fun 給出的唯一元素,而值是每個元素的計數。

範例

iex> Enum.frequencies_by(~w{aa aA bb cc}, &String.downcase/1)
%{"aa" => 2, "bb" => 1, "cc" => 1}

iex> Enum.frequencies_by(~w{aaa aA bbb cc c}, &String.length/1)
%{3 => 2, 2 => 2, 1 => 1}
連結至這個函式

group_by(enumerable, key_fun, value_fun \\ fn x -> x end)

檢視來源
@spec group_by(t(), (element() -> any()), (element() -> any())) :: map()

根據 key_funenumerable 分割成群組。

結果是一個映射,其中每個鍵由 key_fun 給出,每個值是由 value_fun 給出的元素清單。每個清單中元素的順序會從 enumerable 保留下來。然而,就像所有映射一樣,產生的映射是無序的。

範例

iex> Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1)
%{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}

iex> Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1, &String.first/1)
%{3 => ["a", "c"], 5 => ["d"], 7 => ["b"]}

鍵可以是任何 Elixir 值。例如,你可以使用元組依據多個鍵進行分組

iex> collection = [
...>   %{id: 1, lang: "Elixir", seq: 1},
...>   %{id: 1, lang: "Java", seq: 1},
...>   %{id: 1, lang: "Ruby", seq: 2},
...>   %{id: 2, lang: "Python", seq: 1},
...>   %{id: 2, lang: "C#", seq: 2},
...>   %{id: 2, lang: "Haskell", seq: 2},
...> ]
iex> Enum.group_by(collection, &{&1.id, &1.seq})
%{
  {1, 1} => [%{id: 1, lang: "Elixir", seq: 1}, %{id: 1, lang: "Java", seq: 1}],
  {1, 2} => [%{id: 1, lang: "Ruby", seq: 2}],
  {2, 1} => [%{id: 2, lang: "Python", seq: 1}],
  {2, 2} => [%{id: 2, lang: "C#", seq: 2}, %{id: 2, lang: "Haskell", seq: 2}]
}
iex> Enum.group_by(collection, &{&1.id, &1.seq}, &{&1.id, &1.lang})
%{
  {1, 1} => [{1, "Elixir"}, {1, "Java"}],
  {1, 2} => [{1, "Ruby"}],
  {2, 1} => [{2, "Python"}],
  {2, 2} => [{2, "C#"}, {2, "Haskell"}]
}
連結至這個函式

intersperse(enumerable, separator)

檢視來源
@spec intersperse(t(), element()) :: list()

在列舉的每個元素之間插入 separator

範例

iex> Enum.intersperse([1, 2, 3], 0)
[1, 0, 2, 0, 3]

iex> Enum.intersperse([1], 0)
[1]

iex> Enum.intersperse([], 0)
[]
連結至這個函式

into(enumerable, collectable)

檢視來源
@spec into(Enumerable.t(), Collectable.t()) :: Collectable.t()

將給定的 enumerable 插入 collectable 中。

請注意,傳遞一個非空清單作為 collectable 已被棄用。如果你要收集到一個非空的關鍵字清單,請考慮使用 Keyword.merge(collectable, Enum.to_list(enumerable))。如果你要收集到一個非空的清單,請考慮類似 Enum.to_list(enumerable) ++ collectable 的做法。

範例

iex> Enum.into([1, 2], [])
[1, 2]

iex> Enum.into([a: 1, b: 2], %{})
%{a: 1, b: 2}

iex> Enum.into(%{a: 1}, %{b: 2})
%{a: 1, b: 2}

iex> Enum.into([a: 1, a: 2], %{})
%{a: 2}

iex> Enum.into([a: 2], %{a: 1, b: 3})
%{a: 2, b: 3}
連結至這個函式

into(enumerable, collectable, transform)

檢視來源
@spec into(Enumerable.t(), Collectable.t(), (term() -> term())) :: Collectable.t()

根據轉換函數將給定的 enumerable 插入 collectable 中。

範例

iex> Enum.into([1, 2, 3], [], fn x -> x * 3 end)
[3, 6, 9]

iex> Enum.into(%{a: 1, b: 2}, %{c: 3}, fn {k, v} -> {k, v * 2} end)
%{a: 2, b: 4, c: 3}
連結至這個函式

join(enumerable, joiner \\ "")

檢視來源
@spec join(t(), String.t()) :: String.t()

使用 joiner 作為分隔符,將給定的 enumerable 加入成一個字串。

如果 joiner 根本沒有傳遞,它會預設為空字串。

enumerable 中的所有元素都必須可以轉換成字串,否則會引發錯誤。

範例

iex> Enum.join([1, 2, 3])
"123"

iex> Enum.join([1, 2, 3], " = ")
"1 = 2 = 3"

iex> Enum.join([["a", "b"], ["c", "d", "e", ["f", "g"]], "h", "i"], " ")
"ab cdefg h i"
@spec map(t(), (element() -> any())) :: list()

傳回一個清單,其中每個元素都是對 enumerable 的每個對應元素呼叫 fun 的結果。

對於地圖,這個函式會預期一個鍵值元組。

範例

iex> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]

iex> Enum.map([a: 1, b: 2], fn {k, v} -> {k, -v} end)
[a: -1, b: -2]
連結至這個函式

map_every(enumerable, nth, fun)

檢視原始碼 (自 1.4.0 起)
@spec map_every(t(), non_neg_integer(), (element() -> any())) :: list()

傳回一個清單,其中結果是對 enumerable 的每個 nth 元素(從第一個元素開始)呼叫 fun 的結果。

第一個元素總是傳遞給指定的函式,除非 nth0

指定每 nth 個元素的第二個參數必須是非負整數。

如果 nth0,那麼 enumerable 會直接轉換成一個清單,而不會套用 fun

範例

iex> Enum.map_every(1..10, 2, fn x -> x + 1000 end)
[1001, 2, 1003, 4, 1005, 6, 1007, 8, 1009, 10]

iex> Enum.map_every(1..10, 3, fn x -> x + 1000 end)
[1001, 2, 3, 1004, 5, 6, 1007, 8, 9, 1010]

iex> Enum.map_every(1..5, 0, fn x -> x + 1000 end)
[1, 2, 3, 4, 5]

iex> Enum.map_every([1, 2, 3], 1, fn x -> x + 1000 end)
[1001, 1002, 1003]
連結至這個函式

map_intersperse(enumerable, separator, mapper)

檢視原始碼 (自 1.10.0 起)
@spec map_intersperse(t(), element(), (element() -> any())) :: list()

一次對應和插入給定的列舉。

範例

iex> Enum.map_intersperse([1, 2, 3], :a, &(&1 * 2))
[2, :a, 4, :a, 6]
連結至這個函式

map_join(enumerable, joiner \\ "", mapper)

檢視來源
@spec map_join(t(), String.t(), (element() -> String.Chars.t())) :: String.t()

一次對應和加入給定的 enumerable

如果 joiner 根本沒有傳遞,它會預設為空字串。

從呼叫 mapper 回傳的所有元素都必須可以轉換成字串,否則會引發錯誤。

範例

iex> Enum.map_join([1, 2, 3], &(&1 * 2))
"246"

iex> Enum.map_join([1, 2, 3], " = ", &(&1 * 2))
"2 = 4 = 6"
連結至這個函式

map_reduce(enumerable, acc, fun)

檢視來源
@spec map_reduce(t(), acc(), (element(), acc() -> {element(), acc()})) ::
  {list(), acc()}

呼叫給定的函數對 enumerable 中的每個元素,以將其簡化為單一元素,同時保留累加器。

傳回一個元組,其中第一個元素是已對應的列舉,第二個元素是最後的累加器。

函數 fun 接收兩個參數:第一個是元素,第二個是累加器。 fun 必須傳回一個包含兩個元素的元組,格式為 {result, accumulator}

對於映射,第一個元組元素必須是 {key, value} 元組。

範例

iex> Enum.map_reduce([1, 2, 3], 0, fn x, acc -> {x * 2, x + acc} end)
{[2, 4, 6], 6}
連結至這個函式

max(enumerable, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)

檢視來源
@spec max(t(), (element(), element() -> boolean()) | module(), (-> empty_result)) ::
  element() | empty_result
when empty_result: any()

根據 Erlang 的術語排序傳回 enumerable 中的最大元素。

預設情況下,比較使用 >= 分類函數。如果有多個元素被視為最大值,則傳回第一個找到的元素。如果您希望傳回最後一個被視為最大值的元素,則分類函數不應對相等元素傳回 true。

如果列舉為空,則呼叫提供的 empty_fallback。預設 empty_fallback 會引發 Enum.EmptyError

範例

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

此函數使用 Erlang 的術語排序,表示比較是結構性的,而非語義性的。例如

iex> Enum.max([~D[2017-03-31], ~D[2017-04-01]])
~D[2017-03-31]

在上面的範例中,max/2 傳回 3 月 31 日,而非 4 月 1 日,因為結構性比較會比較年分之前的日期。因此,大多數結構提供「比較」函數,例如 Date.compare/2,它會接收兩個結構,並傳回 :lt (小於)、:eq (等於) 和 :gt (大於)。如果您傳遞模組作為分類函數,Elixir 會自動使用該模組的 compare/2 函數

iex> Enum.max([~D[2017-03-31], ~D[2017-04-01]], Date)
~D[2017-04-01]

最後,如果您不希望在列舉為空時引發錯誤,您可以傳遞空回退

iex> Enum.max([], &>=/2, fn -> 0 end)
0
連結至這個函式

max_by(enumerable, fun, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)

檢視來源
@spec max_by(
  t(),
  (element() -> any()),
  (element(), element() -> boolean()) | module(),
  (-> empty_result)
) :: element() | empty_result
when empty_result: any()

傳回 enumerable 中由給定的 fun 計算出的最大元素。

預設情況下,比較使用 >= 分類函數。如果有多個元素被視為最大值,則傳回第一個找到的元素。如果您希望傳回最後一個被視為最大值的元素,則分類函數不應對相等元素傳回 true。

呼叫提供的 empty_fallback 函數,如果 enumerable 為空,則傳回其值。預設 empty_fallback 會引發 Enum.EmptyError

範例

iex> Enum.max_by(["a", "aa", "aaa"], fn x -> String.length(x) end)
"aaa"

iex> Enum.max_by(["a", "aa", "aaa", "b", "bbb"], &String.length/1)
"aaa"

此函數使用 Erlang 的術語排序,表示比較是結構性的,而非語義性的。因此,如果您要比較結構,大多數結構提供「比較」函數,例如 Date.compare/2,它會接收兩個結構,並傳回 :lt (小於)、:eq (等於) 和 :gt (大於)。如果您傳遞模組作為分類函數,Elixir 會自動使用該模組的 compare/2 函數

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.max_by(users, &(&1.birthday), Date)
%{name: "Ellis", birthday: ~D[1943-05-11]}

最後,如果您不希望在列舉為空時引發錯誤,您可以傳遞空回退

iex> Enum.max_by([], &String.length/1, fn -> nil end)
nil
連結至這個函式

member?(可列舉, 元素)

檢視來源
@spec member?(t(), element()) :: boolean()

檢查 元素 是否存在於 可列舉 中。

成員資格會使用配對 (===/2) 算子進行測試。

範例

iex> Enum.member?(1..10, 5)
true
iex> Enum.member?(1..10, 5.0)
false

iex> Enum.member?([1.0, 2.0, 3.0], 2)
false
iex> Enum.member?([1.0, 2.0, 3.0], 2.000)
true

iex> Enum.member?([:a, :b, :c], :d)
false

當在防護區外呼叫時,innot in 算子會使用此函數運作。

連結至這個函式

min(可列舉, 分類器 \\ &<=/2, 空值備用 \\ fn -> raise Enum.EmptyError end)

檢視來源
@spec min(t(), (element(), element() -> boolean()) | module(), (-> empty_result)) ::
  element() | empty_result
when empty_result: any()

根據 Erlang 項順序,傳回 可列舉 中的最小元素。

預設情況下,比較會使用 <= 分類函數。如果有多個元素被視為最小,則會傳回找到的第一個元素。如果您希望傳回被視為最小的最後一個元素,則分類函數不應對相等元素傳回 true。

如果列舉為空,則呼叫提供的 empty_fallback。預設 empty_fallback 會引發 Enum.EmptyError

範例

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

此函數使用 Erlang 的術語排序,表示比較是結構性的,而非語義性的。例如

iex> Enum.min([~D[2017-03-31], ~D[2017-04-01]])
~D[2017-04-01]

在上述範例中,min/2 傳回 4 月 1 日,而不是 3 月 31 日,因為結構比較會比較年份的前一天。因此,大多數結構會提供「比較」函數,例如 Date.compare/2,它會接收兩個結構並傳回 :lt (小於)、:eq (等於) 和 :gt (大於)。如果您傳遞模組作為分類函數,Elixir 會自動使用該模組的 compare/2 函數

iex> Enum.min([~D[2017-03-31], ~D[2017-04-01]], Date)
~D[2017-03-31]

最後,如果您不希望在列舉為空時引發錯誤,您可以傳遞空回退

iex> Enum.min([], fn -> 0 end)
0
連結至這個函式

min_by(可列舉, fun, 分類器 \\ &<=/2, 空值備用 \\ fn -> raise Enum.EmptyError end)

檢視來源
@spec min_by(
  t(),
  (element() -> any()),
  (element(), element() -> boolean()) | module(),
  (-> empty_result)
) :: element() | empty_result
when empty_result: any()

根據指定的 fun 計算,傳回 可列舉 中的最小元素。

預設情況下,比較會使用 <= 分類函數。如果有多個元素被視為最小,則會傳回找到的第一個元素。如果您希望傳回被視為最小的最後一個元素,則分類函數不應對相等元素傳回 true。

呼叫提供的 empty_fallback 函數,如果 enumerable 為空,則傳回其值。預設 empty_fallback 會引發 Enum.EmptyError

範例

iex> Enum.min_by(["a", "aa", "aaa"], fn x -> String.length(x) end)
"a"

iex> Enum.min_by(["a", "aa", "aaa", "b", "bbb"], &String.length/1)
"a"

此函數使用 Erlang 的術語排序,表示比較是結構性的,而非語義性的。因此,如果您要比較結構,大多數結構提供「比較」函數,例如 Date.compare/2,它會接收兩個結構,並傳回 :lt (小於)、:eq (等於) 和 :gt (大於)。如果您傳遞模組作為分類函數,Elixir 會自動使用該模組的 compare/2 函數

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.min_by(users, &(&1.birthday), Date)
%{name: "Lovelace", birthday: ~D[1815-12-10]}

最後,如果您不希望在列舉為空時引發錯誤,您可以傳遞空回退

iex> Enum.min_by([], &String.length/1, fn -> nil end)
nil
連結至這個函式

min_max(可列舉, 空值備用 \\ fn -> raise Enum.EmptyError end)

檢視來源
@spec min_max(t(), (-> empty_result)) :: {element(), element()} | empty_result
when empty_result: any()

根據 Erlang 項順序,傳回一個包含可列舉中最小和最大元素的元組。

如果有多個元素被視為最大或最小,則會傳回找到的第一個元素。

呼叫提供的 empty_fallback 函數,如果 enumerable 為空,則傳回其值。預設 empty_fallback 會引發 Enum.EmptyError

範例

iex> Enum.min_max([2, 3, 1])
{1, 3}

iex> Enum.min_max([], fn -> {nil, nil} end)
{nil, nil}
連結至這個函式

min_max_by(可列舉, fun, 分類器或空值備用 \\ &</2, 空值備用 \\ fn -> raise Enum.EmptyError end)

檢視來源
@spec min_max_by(
  t(),
  (element() -> any()),
  (element(), element() -> boolean()) | module(),
  (-> empty_result)
) :: {element(), element()} | empty_result
when empty_result: any()

根據指定的函數計算,傳回一個包含可列舉中最小和最大元素的元組。

如果有多個元素被視為最大或最小,則會傳回找到的第一個元素。

範例

iex> Enum.min_max_by(["aaa", "bb", "c"], fn x -> String.length(x) end)
{"c", "aaa"}

iex> Enum.min_max_by(["aaa", "a", "bb", "c", "ccc"], &String.length/1)
{"a", "aaa"}

iex> Enum.min_max_by([], &String.length/1, fn -> {nil, nil} end)
{nil, nil}

此函數使用 Erlang 的術語排序,表示比較是結構性的,而非語義性的。因此,如果您要比較結構,大多數結構提供「比較」函數,例如 Date.compare/2,它會接收兩個結構,並傳回 :lt (小於)、:eq (等於) 和 :gt (大於)。如果您傳遞模組作為分類函數,Elixir 會自動使用該模組的 compare/2 函數

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.min_max_by(users, &(&1.birthday), Date)
{
  %{name: "Lovelace", birthday: ~D[1815-12-10]},
  %{name: "Ellis", birthday: ~D[1943-05-11]}
}

最後,如果您不希望在列舉為空時引發錯誤,您可以傳遞空回退

iex> Enum.min_max_by([], &String.length/1, fn -> nil end)
nil
連結至這個函式

product(可列舉)

檢視原始碼 (自 1.12.0 起)
@spec product(t()) :: number()

傳回所有元素的乘積。

如果 enumerable 包含非數字值,則會引發 ArithmeticError

範例

iex> Enum.product([])
1
iex> Enum.product([2, 3, 4])
24
iex> Enum.product([2.0, 3.0, 4.0])
24.0
@spec random(t()) :: element()

傳回 可列舉 中的隨機元素。

如果 enumerable 為空,則會引發 Enum.EmptyError

此函數使用 Erlang 的 :rand 模組 來計算隨機值。請查看其文件以設定不同的隨機演算法或不同的種子。

實作是基於蓄水池抽樣演算法。它假設回傳的範例可以放入記憶體中;輸入的可列舉不必,因為它只會遍歷一次。

如果函式中傳入一個範圍,此函式會在範圍限制中挑選一個隨機值,而不用遍歷整個範圍(因此執行時間和記憶體都是常數)。

範例

以下範例使用:exsss 偽亂數演算法,因為它是 Erlang/OTP 22 的預設值

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {100, 101, 102})
iex> Enum.random([1, 2, 3])
2
iex> Enum.random([1, 2, 3])
1
iex> Enum.random(1..1_000)
309
@spec reduce(t(), (element(), acc() -> acc())) :: acc()

使用累加器,針對 可列舉 中的每個元素呼叫 fun

如果 enumerable 為空,則會引發 Enum.EmptyError

可列舉的第一個元素用作累加器的初始值。然後,函式會使用下一個元素和累加器呼叫。函式回傳的結果會用作下一次反覆運算的累加器,遞迴進行。當可列舉完成時,會回傳最後的累加器。

由於可列舉的第一個元素用作累加器的初始值,fun 只會執行n - 1次,其中n是可列舉的長度。此函式不會為長度為一的可列舉呼叫指定函式。

如果你想為累加器使用另一個值,請使用Enum.reduce/3

範例

iex> Enum.reduce([1, 2, 3, 4], fn x, acc -> x * acc end)
24
連結至這個函式

reduce(可列舉, acc, fun)

檢視來源
@spec reduce(t(), acc(), (element(), acc() -> acc())) :: acc()

使用累加器,針對 可列舉 中的每個元素呼叫 fun

累加器的初始值是acc。函式會使用累加器呼叫可列舉中的每個元素。函式回傳的結果會用作下一次反覆運算的累加器。函式會回傳最後的累加器。

範例

iex> Enum.reduce([1, 2, 3], 0, fn x, acc -> x + acc end)
6

iex> Enum.reduce(%{a: 2, b: 3, c: 4}, 0, fn {_key, val}, acc -> acc + val end)
9

Reduce 作為建構區塊

Reduce(有時稱為fold)是函式程式設計中的基本建構區塊。Enum 模組中幾乎所有的函式都可以實作在 reduce 上。這些函式通常依賴於其他運算,例如Enum.reverse/1,這些運算會由執行時期最佳化。

例如,我們可以透過 reduce/3 來實作 map/2,如下所示

def my_map(enumerable, fun) do
  enumerable
  |> Enum.reduce([], fn x, acc -> [fun.(x) | acc] end)
  |> Enum.reverse()
end

在上面的範例中,Enum.reduce/3 會將每次呼叫 fun 的結果累積成一個清單,並以反向順序排列,最後再呼叫 Enum.reverse/1 來正確排序。

實作像 map/2filter/2 等函式,是了解 Enum.reduce/3 強大的好練習。當 Enum 模組中的函式無法表達某個操作時,開發人員很可能會求助於 reduce/3

連結至這個函式

reduce_while(可列舉, acc, fun)

檢視來源
@spec reduce_while(t(), any(), (element(), any() -> {:cont, any()} | {:halt, any()})) ::
  any()

縮減 可列舉,直到 fun 傳回 {:halt, 項}

預期 fun 的傳回值為

  • {:cont, acc}acc 作為新的累加器繼續縮減,或
  • {:halt, acc} 以停止縮減

如果 fun 傳回 {:halt, acc},縮減就會停止,且函式會傳回 acc。否則,如果可列舉物件已用盡,函式會傳回最後一個 {:cont, acc} 的累加器。

範例

iex> Enum.reduce_while(1..100, 0, fn x, acc ->
...>   if x < 5 do
...>     {:cont, acc + x}
...>   else
...>     {:halt, acc}
...>   end
...> end)
10
iex> Enum.reduce_while(1..100, 0, fn x, acc ->
...>   if x > 0 do
...>     {:cont, acc + x}
...>   else
...>     {:halt, acc}
...>   end
...> end)
5050
@spec reject(t(), (element() -> as_boolean(term()))) :: list()

傳回 可列舉 中元素的清單,排除函數 fun 傳回真值的元素。

另請參閱 filter/2

範例

iex> Enum.reject([1, 2, 3], fn x -> rem(x, 2) == 0 end)
[1, 3]
@spec reverse(t()) :: list()

傳回 可列舉 中元素的清單,順序相反。

範例

iex> Enum.reverse([1, 2, 3])
[3, 2, 1]
@spec reverse(t(), t()) :: list()

反轉 可列舉 中的元素,附加 ,並以清單的形式傳回。

這是針對 enumerable |> Enum.reverse() |> Enum.concat(tail) 的最佳化。

範例

iex> Enum.reverse([1, 2, 3], [4, 5, 6])
[3, 2, 1, 4, 5, 6]
連結至這個函式

reverse_slice(可列舉, 起始索引, 計數)

檢視來源
@spec reverse_slice(t(), non_neg_integer(), non_neg_integer()) :: list()

反轉 可列舉 中從初始 起始索引計數 個元素的範圍。

如果 count 大於 enumerable 其餘部分的大小,則此函式會反轉可列舉物件的其餘部分。

範例

iex> Enum.reverse_slice([1, 2, 3, 4, 5, 6], 2, 4)
[1, 2, 6, 5, 4, 3]
@spec scan(t(), (element(), any() -> any())) :: list()

將給定的函式套用至 enumerable 中的每個元素,將結果儲存在清單中,並將其作為下一次運算的累加器傳遞。使用 enumerable 中的第一個元素作為起始值。

範例

iex> Enum.scan(1..5, &(&1 + &2))
[1, 3, 6, 10, 15]
連結至這個函式

scan(enumerable, acc, fun)

檢視來源
@spec scan(t(), any(), (element(), any() -> any())) :: list()

將給定的函式套用至 enumerable 中的每個元素,將結果儲存在清單中,並將其作為下一次運算的累加器傳遞。使用給定的 acc 作為起始值。

範例

iex> Enum.scan(1..5, 0, &(&1 + &2))
[1, 3, 6, 10, 15]
@spec shuffle(t()) :: list()

傳回一個清單,其中包含 enumerable 的元素,且順序已洗牌。

此函數使用 Erlang 的 :rand 模組 來計算隨機值。請查看其文件以設定不同的隨機演算法或不同的種子。

範例

以下範例使用:exsss 偽亂數演算法,因為它是 Erlang/OTP 22 的預設值

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Enum.shuffle([1, 2, 3])
[3, 2, 1]
iex> Enum.shuffle([1, 2, 3])
[2, 1, 3]
連結至這個函式

slice(enumerable, index_range)

檢視原始碼 (自 1.6.0 起)
@spec slice(t(), Range.t()) :: list()

根據 index_range 傳回給定 enumerable 的子集清單。

index_range 必須為 Range。給定一個 enumerable,它會捨棄 index_range.first(以 0 為基準)之前的元素,然後取用直到元素 index_range.last(包含)的元素。

索引經過正規化,表示負索引將從結尾開始計算(例如,-1 表示 enumerable 的最後一個元素)。

如果 index_range.last 超出範圍,則會將其指定為最後一個元素的索引。

如果正規化後的 index_range.first 超出給定 enumerable 的範圍,或者這個範圍大於正規化後的 index_range.last,則會傳回 []

如果在 index_range 中使用步驟 n(除了 1),則會從 index_range.firstindex_range.last 取用每 n 個元素(根據上述相同的規則)。

範例

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

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

# Last three elements (negative indexes)
iex> Enum.slice([1, 2, 3, 4, 5], -3..-1)
[3, 4, 5]

對於 start > stop 的範圍,您需要明確標記它們為遞增

iex> Enum.slice([1, 2, 3, 4, 5], 1..-2//1)
[2, 3, 4]

步驟可以是任何正數。例如,要取得集合中的每 2 個元素

iex> Enum.slice([1, 2, 3, 4, 5], 0..-1//2)
[1, 3, 5]

要取得前十個元素中的每三個元素

iex> integers = Enum.to_list(1..20)
iex> Enum.slice(integers, 0..9//3)
[1, 4, 7, 10]

如果第一個位置在可列舉的結尾之後或在範圍的最後一個位置之後,則會傳回一個空清單

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

# first is greater than last
iex> Enum.slice([1, 2, 3, 4, 5], 6..5//1)
[]
連結至這個函式

slice(enumerable, start_index, amount)

檢視來源
@spec slice(t(), index(), non_neg_integer()) :: list()

傳回給定 enumerable 的子集清單,從 start_index (以 0 為基準) 開始,包含 amount 個元素(如果有的話)。

給定一個 enumerable,它會捨棄元素 start_index 之前的元素;然後,它會取用 amount 個元素,如果元素不足,則傳回盡可能多的元素。

可以傳遞負的 start_index,表示 enumerable 被列舉一次,且索引從尾端開始計算(例如,-1 從最後一個元素開始切片)。

如果 amount0start_index 超出範圍,則傳回 []

範例

iex> Enum.slice(1..100, 5, 10)
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

# amount to take is greater than the number of elements
iex> Enum.slice(1..10, 5, 100)
[6, 7, 8, 9, 10]

iex> Enum.slice(1..10, 5, 0)
[]

# using a negative start index
iex> Enum.slice(1..10, -6, 3)
[5, 6, 7]
iex> Enum.slice(1..10, -11, 5)
[1, 2, 3, 4, 5]

# out of bound start index
iex> Enum.slice(1..10, 10, 5)
[]
連結至這個函式

slide(enumerable, range_or_single_index, insertion_index)

檢視原始碼 (自 1.13.0 起)
@spec slide(t(), Range.t() | index(), index()) :: list()

range_or_single_index 給定的單一或多個元素從 enumerable 滑動到 insertion_index

要移動的範圍語意與 Enum.slice/2 的語意相同。具體來說,表示

  • 索引已正規化,表示負索引會從尾端開始計算(例如,-1 表示列舉項目的最後一個元素)。對於像清單這類無法提供恆定時間計算的類型,這將導致列舉項目兩次遍歷。

  • 如果正規化索引範圍的 last 超出範圍,則範圍會截斷到最後一個元素。

  • 如果正規化索引範圍的 first 超出範圍,則選取的滑動範圍會是空的,因此您會取回輸入清單。

  • 遞減的範圍(例如 5..0//1)也會選取一個空的範圍來移動,因此您會取回輸入清單。

  • 任何步驟不是 1 的範圍都會引發錯誤。

範例

# Slide a single element
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 5, 1)
[:a, :f, :b, :c, :d, :e, :g]

# Slide a range of elements backward
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 3..5, 1)
[:a, :d, :e, :f, :b, :c, :g]

# Slide a range of elements forward
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 1..3, 5)
[:a, :e, :f, :b, :c, :d, :g]

# Slide with negative indices (counting from the end)
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 3..-1//1, 2)
[:a, :b, :d, :e, :f, :g, :c]
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], -4..-2, 1)
[:a, :d, :e, :f, :b, :c, :g]

# Insert at negative indices (counting from the end)
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 3, -1)
[:a, :b, :c, :e, :f, :g, :d]
@spec sort(t()) :: list()

根據 Erlang 的術語排序對 enumerable 進行排序。

此函式使用合併排序演算法。請勿使用此函式來排序結構,請參閱 sort/2 以取得更多資訊。

範例

iex> Enum.sort([3, 2, 1])
[1, 2, 3]
@spec sort(
  t(),
  (element(), element() -> boolean())
  | :asc
  | :desc
  | module()
  | {:asc | :desc, module()}
) :: list()

根據給定的函式對 enumerable 進行排序。

此函式使用合併排序演算法。所提供的函式應比較兩個引數,並在第一個引數先於或與第二個引數相同時傳回 true

範例

iex> Enum.sort([1, 2, 3], &(&1 >= &2))
[3, 2, 1]

只要所提供的函式對視為相等的數值傳回 true,排序演算法就會是穩定的

iex> Enum.sort(["some", "kind", "of", "monster"], &(byte_size(&1) <= byte_size(&2)))
["of", "some", "kind", "monster"]

如果函式未對相等數值傳回 true,則排序是不穩定的,且相等項目的順序可能會洗牌。例如

iex> Enum.sort(["some", "kind", "of", "monster"], &(byte_size(&1) < byte_size(&2)))
["of", "kind", "some", "monster"]

遞增和遞減 (自 v1.10.0 起)

sort/2 允許開發人員傳遞 :asc:desc 作為排序器,這方便 &<=/2&>=/2 分別使用。

iex> Enum.sort([2, 3, 1], :asc)
[1, 2, 3]
iex> Enum.sort([2, 3, 1], :desc)
[3, 2, 1]

排序結構

排序結構時,請勿使用 </2<=/2>/2>=/2 及其相關函數。這是因為上述內建運算子會執行結構比較,而非語意比較。假設我們要對下列日期清單進行排序

iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates)
[~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]

請注意,傳回的結果不正確,因為 sort/1 預設會使用 <=/2,而它會比較它們的結構。比較結構時,會按照字母順序比較欄位,這表示上述日期會依 daymonth,再依 year 進行比較,這與我們預期的相反。

因此,大多數結構會提供「比較」函數,例如 Date.compare/2,它會接收兩個結構並傳回 :lt (小於)、:eq (等於) 和 :gt (大於)。如果您傳遞模組作為排序函數,Elixir 會自動使用該模組的 compare/2 函數

iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates, Date)
[~D[2019-01-01], ~D[2019-06-06], ~D[2020-03-02]]

若要按遞減順序擷取所有日期,您可以使用 :asc:desc 將模組包在一個元組中,並將其作為第一個元素

iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates, {:asc, Date})
[~D[2019-01-01], ~D[2019-06-06], ~D[2020-03-02]]
iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates, {:desc, Date})
[~D[2020-03-02], ~D[2019-06-06], ~D[2019-01-01]]
連結至這個函式

sort_by(enumerable, mapper, sorter \\ :asc)

檢視來源
@spec sort_by(
  t(),
  (element() -> mapped_element),
  (element(), element() -> boolean())
  | :asc
  | :desc
  | module()
  | {:asc | :desc, module()}
) :: list()
when mapped_element: element()

根據提供的 sorter 函式對 enumerable 的對應結果進行排序。

此函數會使用提供的 mapper 函數對 enumerable 的每個元素進行對應。接著,會使用 sorter 對對應的元素進行排序,其預設值為 :asc,並會以遞增順序對元素進行排序。

sort_by/3sort/2 的不同之處在於,它只會計算 enumerable 中每個元素的比較值一次,而不是在每次比較中為每個元素計算一次。如果對兩個元素呼叫相同的函數,使用 sort_by/3 會更有效率。

遞增和遞減 (自 v1.10.0 起)

sort_by/3 允許開發人員傳遞 :asc:desc 作為 sorter,這分別是 &<=/2&>=/2 的簡便寫法

iex> Enum.sort_by([2, 3, 1], &(&1), :asc)
[1, 2, 3]

iex> Enum.sort_by([2, 3, 1], &(&1), :desc)
[3, 2, 1]

範例

使用 sorter 的預設值 :asc

iex> Enum.sort_by(["some", "kind", "of", "monster"], &byte_size/1)
["of", "some", "kind", "monster"]

依據多個屬性排序 - 先依據大小,再依據第一個字母 (這利用了元組按元素比較的事實)

iex> Enum.sort_by(["some", "kind", "of", "monster"], &{byte_size(&1), String.first(&1)})
["of", "kind", "some", "monster"]

類似於 sort/2,你可以傳遞自訂的排序器

iex> Enum.sort_by(["some", "kind", "of", "monster"], &byte_size/1, :desc)
["monster", "some", "kind", "of"]

sort/2 一樣,避免使用預設的排序函式來排序結構,因為它預設執行結構比較,而不是語義比較。在這種情況下,你應傳遞排序函式作為第三個元素或任何實作 compare/2 函式的模組。例如,分別依據使用者的生日以遞增和遞減順序排序

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.sort_by(users, &(&1.birthday), Date)
[
  %{name: "Lovelace", birthday: ~D[1815-12-10]},
  %{name: "Turing", birthday: ~D[1912-06-23]},
  %{name: "Ellis", birthday: ~D[1943-05-11]}
]
iex> Enum.sort_by(users, &(&1.birthday), {:desc, Date})
[
  %{name: "Ellis", birthday: ~D[1943-05-11]},
  %{name: "Turing", birthday: ~D[1912-06-23]},
  %{name: "Lovelace", birthday: ~D[1815-12-10]}
]

效能特性

如初始區段所述,sort_by/3 計算可列舉中每個元素的比較值一次,而不是每次比較中每個元素一次。這表示 sort_by/3 必須對資料進行初始傳遞以計算這些值。

但是,如果這些值很容易計算,例如,你已經將想要排序的欄位萃取到元組中,那麼這些額外的傳遞就會變成負擔。在這種情況下,請考慮改用 List.keysort/3

我們來看一個範例。想像你有一個產品清單,還有一個 ID 清單。你想要保留給定 ID 中的所有產品,並依據其價格對其名稱進行排序。你可以這樣寫

for(
  product <- products,
  product.id in ids,
  do: product
)
|> Enum.sort_by(& &1.price)
|> Enum.map(& &1.name)

但是,你也可以這樣寫

for(
  product <- products,
  product.id in ids,
  do: {product.name, product.price}
)
|> List.keysort(1)
|> Enum.map(&elem(&1, 0))

對於效能敏感的程式碼,使用 List.keysort/3 會是更好的選擇,因為它避免了額外的遍歷。

@spec split(t(), integer()) :: {list(), list()}

enumerable 分割成兩個 enumerable,在第一個中保留 count 個元素。

如果 count 是負數,它會從 enumerable 的最後開始往回計數。

請注意,負 count 表示 enumerable 將被列舉兩次:一次計算位置,第二次執行實際分割。

範例

iex> Enum.split([1, 2, 3], 2)
{[1, 2], [3]}

iex> Enum.split([1, 2, 3], 10)
{[1, 2, 3], []}

iex> Enum.split([1, 2, 3], 0)
{[], [1, 2, 3]}

iex> Enum.split([1, 2, 3], -1)
{[1, 2], [3]}

iex> Enum.split([1, 2, 3], -5)
{[], [1, 2, 3]}
連結至這個函式

split_while(enumerable, fun)

檢視來源
@spec split_while(t(), (element() -> as_boolean(term()))) :: {list(), list()}

fun 首次對元素傳回假值 (falsenil) 的位置,將 enumerable 分割成兩個。

傳回一個二元組,其中包含兩個元素清單。觸發分割的元素是第二個清單的一部分。

範例

iex> Enum.split_while([1, 2, 3, 4], fn x -> x < 3 end)
{[1, 2], [3, 4]}

iex> Enum.split_while([1, 2, 3, 4], fn x -> x < 0 end)
{[], [1, 2, 3, 4]}

iex> Enum.split_while([1, 2, 3, 4], fn x -> x > 0 end)
{[1, 2, 3, 4], []}
連結至這個函式

split_with(enumerable, fun)

檢視原始碼 (自 1.4.0 起)
@spec split_with(t(), (element() -> as_boolean(term()))) :: {list(), list()}

根據給定的函式 funenumerable 分割成兩個清單。

透過呼叫 fun,並將 enumerable 中的每個元素作為其唯一參數,將指定的 enumerable 分割成兩個清單。傳回一個二元組,其中第一個清單包含 enumerable 中所有套用 fun 後傳回真值的元素,而第二個清單則包含所有套用 fun 後傳回假值的元素(falsenil)。

傳回清單中元素的相對順序與其在原始可列舉中的順序相同(如果可列舉是有序的,例如清單)。請參閱下列範例。

範例

iex> Enum.split_with([5, 4, 3, 2, 1, 0], fn x -> rem(x, 2) == 0 end)
{[4, 2, 0], [5, 3, 1]}

iex> Enum.split_with([a: 1, b: -2, c: 1, d: -3], fn {_k, v} -> v < 0 end)
{[b: -2, d: -3], [a: 1, c: 1]}

iex> Enum.split_with([a: 1, b: -2, c: 1, d: -3], fn {_k, v} -> v > 50 end)
{[], [a: 1, b: -2, c: 1, d: -3]}

iex> Enum.split_with([], fn {_k, v} -> v > 50 end)
{[], []}
@spec sum(t()) :: number()

傳回所有元素的總和。

如果 enumerable 包含非數字值,則會引發 ArithmeticError

範例

iex> Enum.sum([1, 2, 3])
6

iex> Enum.sum(1..10)
55

iex> Enum.sum(1..10//2)
25
@spec take(t(), integer()) :: list()

列舉的開始或結束處取出數量的元素。

如果指定正數 amount,則會從 enumerable 開頭擷取 amount 個元素。

如果指定負數 amount,則會從結尾擷取 amount 個元素。會列舉 enumerable 一次以取得正確的索引,並從結尾執行其餘的計算。

如果 amount 為 0,則會傳回 []

範例

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

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

iex> Enum.take([1, 2, 3], 0)
[]

iex> Enum.take([1, 2, 3], -1)
[3]
連結至這個函式

take_every(列舉, 第n個)

檢視來源
@spec take_every(t(), non_neg_integer()) :: list()

列舉中的第一個元素開始,傳回第n個元素的清單。

第一個元素始終會包含在內,除非 nth 為 0。

指定每 nth 個元素的第二個參數必須是非負整數。

範例

iex> Enum.take_every(1..10, 2)
[1, 3, 5, 7, 9]

iex> Enum.take_every(1..10, 0)
[]

iex> Enum.take_every([1, 2, 3], 1)
[1, 2, 3]
連結至這個函式

take_random(列舉, 計數)

檢視來源
@spec take_random(t(), non_neg_integer()) :: list()

列舉中取出計數個隨機元素。

請注意,此函式會遍歷整個 enumerable 以取得隨機子清單。

請參閱 random/1 以取得有關實作和隨機種子的注意事項。

範例

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Enum.take_random(1..10, 2)
[3, 1]
iex> Enum.take_random(?a..?z, 5)
'mikel'
連結至這個函式

take_while(列舉, 函數)

檢視來源
@spec take_while(t(), (element() -> as_boolean(term()))) :: list()

列舉的開始處取出元素,同時函數傳回真值。

範例

iex> Enum.take_while([1, 2, 3], fn x -> x < 3 end)
[1, 2]
@spec to_list(t()) :: [element()]

列舉轉換為清單。

範例

iex> Enum.to_list(1..3)
[1, 2, 3]
@spec uniq(t()) :: list()

列舉列舉,移除所有重複的元素。

範例

iex> Enum.uniq([1, 2, 3, 3, 2, 1])
[1, 2, 3]
@spec uniq_by(t(), (element() -> term())) :: list()

列舉列舉,移除函數函數傳回重複元素的元素。

函數 fun 將每個元素對應到一個項目。如果兩個元素的 fun 回傳值相等,則這兩個元素視為重複。

會保留每個元素第一次出現的項目。

範例

iex> Enum.uniq_by([{1, :x}, {2, :y}, {1, :z}], fn {x, _} -> x end)
[{1, :x}, {2, :y}]

iex> Enum.uniq_by([a: {:tea, 2}, b: {:tea, 2}, c: {:coffee, 1}], fn {_, y} -> y end)
[a: {:tea, 2}, c: {:coffee, 1}]
@spec unzip(t()) :: {[element()], [element()]}

zip/2的反義詞。從給定的列舉中萃取二元組,並將它們分組在一起。

它接收一個 可列舉,其元素為兩個元素的元組,並回傳一個元組,其中包含兩個清單,每個清單分別由每個元組的第一個和第二個元素組成。

除非 可列舉 是或可以轉換為元組清單,且每個元組中正好包含兩個元素,否則此函數會失敗。

範例

iex> Enum.unzip([{:a, 1}, {:b, 2}, {:c, 3}])
{[:a, :b, :c], [1, 2, 3]}
連結至這個函式

with_index(列舉, 函數或偏移量 \\ 0)

檢視來源
@spec with_index(t(), integer()) :: [{term(), integer()}]
@spec with_index(t(), (element(), index() -> value)) :: [value] when value: any()

傳回列舉,每個元素都封裝在一個元組中,並附帶其索引。

可以接收函數或整數偏移量。

如果給定 偏移量,它將從給定的偏移量而不是從零開始索引。

如果給定 函數,它將透過對可列舉的每個元素和索引(從零開始)呼叫函數來索引。

範例

iex> Enum.with_index([:a, :b, :c])
[a: 0, b: 1, c: 2]

iex> Enum.with_index([:a, :b, :c], 3)
[a: 3, b: 4, c: 5]

iex> Enum.with_index([:a, :b, :c], fn element, index -> {index, element} end)
[{0, :a}, {1, :b}, {2, :c}]
連結至這個函式

zip(列舉)

檢視原始碼 (自 1.4.0 起)
@spec zip(enumerables) :: [tuple()] when enumerables: [t()] | t()

將有限集合中對應的列舉元素壓縮成元組清單。

只要給定集合中的任何可列舉完成,就會完成壓縮。

範例

iex> Enum.zip([[1, 2, 3], [:a, :b, :c], ["foo", "bar", "baz"]])
[{1, :a, "foo"}, {2, :b, "bar"}, {3, :c, "baz"}]

iex> Enum.zip([[1, 2, 3, 4, 5], [:a, :b, :c]])
[{1, :a}, {2, :b}, {3, :c}]
@spec zip(t(), t()) :: [{any(), any()}]

將兩個列舉中對應的元素壓縮成元組清單。

只要任一可列舉完成,就會完成壓縮。

範例

iex> Enum.zip([1, 2, 3], [:a, :b, :c])
[{1, :a}, {2, :b}, {3, :c}]

iex> Enum.zip([1, 2, 3, 4, 5], [:a, :b, :c])
[{1, :a}, {2, :b}, {3, :c}]
連結至這個函式

zip_reduce(列舉, acc, 縮減器)

檢視原始碼 (自 1.12.0 起)
@spec zip_reduce(t(), acc, ([term()], acc -> acc)) :: acc when acc: term()

縮減所有給定的列舉,只要任何列舉為空就停止。

還原器將接收 2 個參數:元素清單(每個列舉一個)和累加器。

在實務上,此函數提供的行為可以用下列方式達成:

Enum.reduce(Stream.zip(enums), acc, reducer)

zip_reduce/3 是為了方便而存在的。

範例

iex> enums = [[1, 1], [2, 2], [3, 3]]
...>  Enum.zip_reduce(enums, [], fn elements, acc ->
...>    [List.to_tuple(elements) | acc]
...> end)
[{1, 2, 3}, {1, 2, 3}]

iex> enums = [[1, 2], [a: 3, b: 4], [5, 6]]
...> Enum.zip_reduce(enums, [], fn elements, acc ->
...>   [List.to_tuple(elements) | acc]
...> end)
[{2, {:b, 4}, 6}, {1, {:a, 3}, 5}]
連結至這個函式

zip_reduce(左, 右, acc, 縮減器)

檢視原始碼 (自 1.12.0 起)
@spec zip_reduce(
  t(),
  t(),
  acc,
  (enum1_elem :: term(), enum2_elem :: term(), acc -> acc)
) :: acc
when acc: term()

縮減兩個列舉,只要任何列舉為空就停止。

在實務上,此函數提供的行為可以用下列方式達成:

Enum.reduce(Stream.zip(left, right), acc, reducer)

zip_reduce/4 是為了方便而存在的。

範例

iex> Enum.zip_reduce([1, 2], [3, 4], 0, fn x, y, acc -> x + y + acc end)
10

iex> Enum.zip_reduce([1, 2], [3, 4], [], fn x, y, acc -> [x + y | acc] end)
[6, 4]
連結至這個函式

zip_with(列舉, zip_函數)

檢視原始碼 (自 1.12.0 起)
@spec zip_with(t(), ([term()] -> term())) :: [term()]

將有限集合中對應的列舉元素壓縮成清單,並在過程中使用zip_函數函數轉換它們。

每個列舉中第一個元素將會放入一個清單中,然後傳遞給一元 zip_fun 函式。接著,每個列舉中的第二個元素會放入一個清單中,並傳遞給 zip_fun,以此類推,直到 enumerables 中的任何一個列舉用盡元素。

傳回一個清單,其中包含呼叫 zip_fun 的所有結果。

範例

iex> Enum.zip_with([[1, 2], [3, 4], [5, 6]], fn [x, y, z] -> x + y + z end)
[9, 12]

iex> Enum.zip_with([[1, 2], [3, 4]], fn [x, y] -> x + y end)
[4, 6]
連結至這個函式

zip_with(列舉1, 列舉2, zip_函數)

檢視原始碼 (自 1.12.0 起)
@spec zip_with(t(), t(), (enum1_elem :: term(), enum2_elem :: term() -> term())) :: [
  term()
]

將兩個列舉中對應的元素壓縮成清單,並在過程中使用zip_函數函數轉換它們。

每個集合的對應元素會依序傳遞給提供的二元 zip_fun 函式。傳回一個清單,其中包含對每個元素對呼叫 zip_fun 的結果。

一旦任一列舉用盡元素,就會完成合併。

合併映射

重要的是要記住,合併本質上依賴於順序。如果您合併兩個清單,您將依序取得每個清單中索引的元素。如果我們合併兩個映射,您可能會認為您將取得左邊映射中的給定金鑰和右邊映射中的匹配金鑰,但沒有這樣的保證,因為映射金鑰沒有順序!請考慮以下內容

left =  %{:a => 1, 1 => 3}
right = %{:a => 1, :b => :c}
Enum.zip(left, right)
# [{{1, 3}, {:a, 1}}, {{:a, 1}, {:b, :c}}]

如您所見,:a 沒有與 :a 配對。如果您需要這樣,您應該使用 Map.merge/3

範例

iex> Enum.zip_with([1, 2], [3, 4], fn x, y -> x + y end)
[4, 6]

iex> Enum.zip_with([1, 2], [3, 4, 5, 6], fn x, y -> x + y end)
[4, 6]

iex> Enum.zip_with([1, 2, 5, 6], [3, 4], fn x, y -> x + y end)
[4, 6]