返回地图或转换为地图?字数灵药

ltr*_*npr 2 elixir

研究Elixir中的运动词计数问题.目标是返回一个包含句子中每个单词的字数的地图.即如果字符串"一条鱼两条鱼红鱼蓝鱼"是输入应该是输入%{ "one" => 1 , "fish" => 4 , "two" => 1 , "red" => 1 , "blue" => 1 }

这是我得到的:

iex(14)> sentence = "one fish two fish red fish blue fish"
"one fish two fish red fish blue fish"
iex(15)> String.split(sentence)                                                                         
["one", "fish", "two", "fish", "red", "fish", "blue", "fish"]
iex(16)> String.split(sentence) |> Enum.group_by(fn(x) -> x end)
%{"blue" => ["blue"], "fish" => ["fish", "fish", "fish", "fish"],
  "one" => ["one"], "red" => ["red"], "two" => ["two"]}
Run Code Online (Sandbox Code Playgroud)

如何迭代此映射并对值运行Enum.count?我试过了Enum.map(fn {k, v} -> {k, Enum.count(v)} end),但是返回了一个元组列表[{"blue", 1}, {"fish", 4}, {"one", 1}, {"red", 1}, {"two", 1}].我是否需要将元组转换为映射,还是有更好的方法?如果我需要将元组转换为地图类型,我该怎么做?

我是Elixir和Erlang的新手,所以如果有人能告诉我为什么当你将地图传递给Enum.map函数时,你会得到一个元组列表而不是一个有用的地图.

Gaz*_*ler 6

您可以使用Enum.into/2转换对的列表(具有2个元素的元组):

[{"blue", 1}, {"fish", 4}, {"one", 1}, {"red", 1}, {"two", 1}] |> Enum.into(%{})
Run Code Online (Sandbox Code Playgroud)

您可以将Enum.reduce/3转换为新地图,以防止额外的枚举:

String.split(sentence)
|> Enum.group_by(fn(x) -> x end)
|> Enum.reduce(%{}, fn {k, v}, acc -> Map.put(acc, k, Enum.count(v)) end)
Run Code Online (Sandbox Code Playgroud)

在可枚举协议的实现中,映射显式转换为对的列表:https://github.com/elixir-lang/elixir/blob/v1.1.1/lib/elixir/lib/enum.ex#L2619

您可以使用Enum.reduce和Map.update/4一次性计算列表中的单词:

String.split(sentence)
|> Enum.reduce(%{}, fn word, acc -> Map.update(acc, word, 1, &(&1 + 1)) end)
Run Code Online (Sandbox Code Playgroud)