研究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"]}
如何迭代此地图并对值运行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函数时,你会得到一个元组列表而不是一个有用的地图。
答案 0 :(得分:6)
您可以使用Enum.into/2转换成对列表(包含2个元素的元组):
[{"blue", 1}, {"fish", 4}, {"one", 1}, {"red", 1}, {"two", 1}] |> Enum.into(%{})
您可以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)
地图在Enumerable协议的实现中明确转换为对的列表: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)
答案 1 :(得分:0)
注意:有了elixir-1.10
,您可以利用Enum.frequencies
功能。
"one fish two fish red fish blue fish"
|> String.split(" ")
|> Enum.frequencies
这样,您就可以使用管道操作器?