Elixir語言中 Kernel.SpecialForms.for
相關用法介紹如下。
用法:
for(args)
(宏)
理解允許您從可枚舉或位串快速構建數據結構。
讓我們從一個例子開始:
iex> for n <- [1, 2, 3, 4], do: n * 2
[2, 4, 6, 8]
推導式接受許多生成器和過濾器。可枚舉生成器使用 <-
定義:
# A list generator:
iex> for n <- [1, 2, 3, 4], do: n * 2
[2, 4, 6, 8]
# A comprehension with two generators
iex> for x <- [1, 2], y <- [2, 3], do: x * y
[2, 3, 4, 6]
也可以給出過濾器:
# A comprehension with a generator and a filter
iex> for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n
[2, 4, 6]
生成器也可用於過濾,因為它會刪除與 <-
左側的模式不匹配的任何值:
iex> users = [user: "john", admin: "meg", guest: "barbara"]
iex> for {type, name} when type != :guest <- users do
...> String.upcase(name)
...> end
["JOHN", "MEG"]
位串生成器也受支持,並且在您需要組織位串流時非常有用:
iex> pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
iex> for <<r::8, g::8, b::8 <- pixels>>, do: {r, g, b}
[{213, 45, 132}, {64, 76, 32}, {76, 0, 0}, {234, 32, 15}]
理解內的變量賦值,無論是在生成器、過濾器還是塊內,都不會反映在理解之外。
:into
和 :uniq
選項
在上麵的示例中,推導式返回的結果始終是一個列表。返回的結果可以通過傳遞 :into
選項來配置,隻要它實現
協議,它就可以接受任何結構。Collectable
例如,我們可以使用帶有:into
選項的位串生成器來輕鬆刪除字符串中的所有空格:
iex> for <<c <- " hello world ">>, c != ?\s, into: "", do: <<c>>
"helloworld"
模塊提供流,它們都是 IO
和 Enumerable
,這是一個使用理解的大寫回顯服務器:Collectable
for line <- IO.stream(), into: IO.stream() do
String.upcase(line)
end
類似地,uniq: true
也可以用於理解,以保證隻有在之前沒有返回結果的情況下才會將結果添加到集合中。例如:
iex> for x <- [1, 1, 2, 3], uniq: true, do: x * 2
[2, 4, 6]
iex> for <<x <- "abcabc">>, uniq: true, into: "", do: <<x - 32>>
"ABC"
:reduce
選項
雖然:into
選項允許我們自定義對給定數據類型的理解行為,例如將所有值放入映射或二進製文件中,但這並不總是足夠的。
例如,假設您有一個帶有字母的二進製文件,您想計算每個小寫字母出現的次數,忽略所有大寫字母。例如,對於字符串 "AbCabCABc"
,我們要返回映射 %{"a" => 1, "b" => 2, "c" => 1}
。
如果我們要使用 :into
,我們需要一個數據類型來計算它所擁有的每個元素的頻率。雖然 Elixir 中沒有這樣的數據類型,但您可以自己實現一個。
一個更簡單的選擇是對字母的映射和過濾使用理解,然後我們調用
來構建一個映射,例如:Enum.reduce/3
iex> letters = for <<x <- "AbCabCABc">>, x in ?a..?z, do: <<x>>
iex> Enum.reduce(letters, %{}, fn x, acc -> Map.update(acc, x, 1, & &1 + 1) end)
%{"a" => 1, "b" => 2, "c" => 1}
雖然上麵是straight-forward,但它的缺點是至少要遍曆數據兩次。如果您期望長字符串作為輸入,這可能會非常昂貴。
幸運的是,推導式也支持 :reduce
選項,這將允許我們將上述兩個步驟融合為一個步驟:
iex> for <<x <- "AbCabCABc">>, x in ?a..?z, reduce: %{} do
...> acc -> Map.update(acc, <<x>>, 1, & &1 + 1)
...> end
%{"a" => 1, "b" => 2, "c" => 1}
當給定:reduce
鍵時,其值用作初始累加器,必須將do
塊更改為使用->
子句,其中->
的左側接收上一次迭代的累加值,右側的表達式必須返回新的累加器值。一旦沒有更多元素,則返回最終的累加值。如果根本沒有元素,則返回初始累加器值。
相關用法
- Elixir Kernel.SpecialForms.fn用法及代碼示例
- Elixir Kernel.SpecialForms.case用法及代碼示例
- Elixir Kernel.SpecialForms.%{}用法及代碼示例
- Elixir Kernel.SpecialForms.quote用法及代碼示例
- Elixir Kernel.SpecialForms.require用法及代碼示例
- Elixir Kernel.SpecialForms.&expr用法及代碼示例
- Elixir Kernel.SpecialForms.<<args>>用法及代碼示例
- Elixir Kernel.SpecialForms.{args}用法及代碼示例
- Elixir Kernel.SpecialForms.unquote_splicing用法及代碼示例
- Elixir Kernel.SpecialForms.receive用法及代碼示例
- Elixir Kernel.SpecialForms.%struct{}用法及代碼示例
- Elixir Kernel.SpecialForms.import用法及代碼示例
- Elixir Kernel.SpecialForms.left . right用法及代碼示例
- Elixir Kernel.SpecialForms.alias用法及代碼示例
- Elixir Kernel.SpecialForms.try用法及代碼示例
- Elixir Kernel.SpecialForms.cond用法及代碼示例
- Elixir Kernel.SpecialForms.__aliases__用法及代碼示例
- Elixir Kernel.SpecialForms.left :: right用法及代碼示例
- Elixir Kernel.SpecialForms.unquote用法及代碼示例
- Elixir Kernel.SpecialForms.with用法及代碼示例
- Elixir Kernel.SpecialForms.__block__用法及代碼示例
- Elixir Kernel.SpecialForms.^var用法及代碼示例
- Elixir Kernel.round用法及代碼示例
- Elixir Kernel.left / right用法及代碼示例
- Elixir Kernel.put_in用法及代碼示例
注:本文由純淨天空篩選整理自elixir-lang.org大神的英文原創作品 Kernel.SpecialForms.for(args)。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。