elixir的列表解析 (List comprehensions)

 

列表解析 (List comprehensions) 是erlang中的语法糖,同样,在elixir中也有对应的语法。

在很多時候,解析可以用来叠代产生更简洁的语句。让我们先来看一个简单的解析,然后拆解它的结构:EnumStream

iex> list = [1, 2, 3, 4, 5]
iex> for x <- list, do: x*x
[1, 4, 9, 16, 25]

我們注意到的第一件事是使用 和生成器 (generator)。生成器是什么?生成器是在列表解析中找到的 表達式,它负责产生下一个值。forx <- [1, 2, 3, 4]

對我們來說幸運的是,解析不僅限於列表,实际上它能在任何举例上使用:

# Keyword Lists
iex> for {_key, val} <- [one: 1, two: 2, three: 3], do: val
[1, 2, 3]

# Maps
iex> for {k, v} <- %{"a" => "A", "b" => "B"}, do: {k, v}
[{"a", "A"}, {"b", "B"}]

# Binaries
iex> for <<c <- "hello">>, do: <<c>>
["h", "e", "l", "l", "o"]

如同 Elixir 中的許多其他東西,生成器依靠模式比對將其輸入集 (input set) 與左側變數進行比較。在無法找到配對的情況下,該值將被忽略:

iex> for {:ok, val} <- [ok: "Hello", error: "Unknown", ok: "World"], do: val
["Hello", "World"]

可以同時使用多個生成器,就像巢狀迴圈一樣 (nested loops):

iex> list = [1, 2, 3, 4]
iex> for n <- list, times <- 1..n do
iex>   String.duplicate("*", times)
iex> end
["*", "*", "**", "*", "**", "***", "*", "**", "***", "****"]

(备注):可以拆解为:

iex(28)> for  times <- 1..1  do String.duplicate("*",times) end
["*"]
iex(29)> for  times <- 1..2  do String.duplicate("*",times) end
["*", "**"]
iex(30)> for  times <- 1..3  do String.duplicate("*",times) end
["*", "**", "***"]
iex(31)> for  times <- 1..4  do String.duplicate("*",times) end
["*", "**", "***", "****"]

  

为了更好的说明正在执行的循环,我们使用 示例 两个被生成的值: IO.puts

iex> for n <- list, times <- 1..n, do: IO.puts "#{n} - #{times}"
1 - 1
2 - 1
2 - 2
3 - 1
3 - 2
3 - 3
4 - 1
4 - 2
4 - 3
4 - 4

列表解析是語法糖,只有在適當的時候才應該使用。

解析器(Filters)

可以把篩選器看作是解析式的监视 (guard)。當篩選值回傳 或 時,它將被排除在最終列表之外。让我们在一个范围内循环,并只注意偶數。我們將使用 Integer 模組中的 函數來檢查一個值是否是偶數。falsenilis_even/1

import Integer
iex> for x <- 1..10, is_even(x), do: x
[2, 4, 6, 8, 10]

如同生成器 (generators),可以同時使用多個篩選器。現在擴展範圍,然後僅對偶數且可被 3 整除的值進行篩選。

import Integer
iex> for x <- 1..100,
...>   is_even(x),
...>   rem(x, 3) == 0, do: x
[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]

使用 :into

如果想產生一個列表 (list) 以外的東西呢?加入 選項,就可以做到這一點!經驗上來說, 接受任何能實現 協定的結構。:into:intoCollectable

要使用,让我们从关键字列表中建立一个映射:  :into

iex> for {k, v} <- [one: 1, two: 2, three: 3], into: %{}, do: {k, v}
%{one: 1, three: 3, two: 2}

由於二進位 (binaries) 也是可群集 (collectables) 的,所以可以使用列表解析和 來建立字串::into

iex> for c <- [72, 101, 108, 108, 111], into: "", do: <<c>>
"Hello"

参考链接:

http://elixir-lang.org/getting-started/comprehensions.html
 
列表过滤:

iex(1)> Enum.filter(["person.name", "person.email", "person.tel", "bot.name"], fn(x) ->
    String.starts_with?(x, "person")
   end)
["person.name", "person.email", "person.tel"]

 
  # ## 列表解析comprehensions  ,  elixir和erlang的语法

  # for n <- [1, 2, 3, 4], do: n * n

  # [X * X || X <-lists:seq(1,4) ]

  

 
posted @ 2022-06-24 11:27  孤独信徒  阅读(117)  评论(0编辑  收藏  举报