繁体   English   中英

循环遍历值列表,在键中查找匹配项并在 Elixir 中对匹配值求和

[英]Loop through a list of values, find matches in keys and sum matched values in Elixir

我正在学习 Elixir 并且我在解决这个简单问题时遇到了困难:

我有一个值列表:

my_list = ["a", "b", "c", "y", "z", "a", "e"]

我有一个 map:

my_map = %{"a" => -1, "b" => 0, "c" => 1, "d" => 2, "e" => 3}

我想遍历my_list ,在 my_map 中找到所有关键事件,如果发生,则对my_map中的值my_map

在上面的示例中,它应该返回 2,因为:

-1 + 0 + 1 + (ignored) + (ignored) - 1 + 3

# => 2

在具有可变变量的语言中,这是一件非常容易做到的事情(我们可以循环列表并添加一个计数器)。 我正在努力改变我的心态。

谢谢你的帮助!

我正在努力改变我的心态。

令人钦佩。 如果您愿意改变思维方式并尝试更实用地思考,您会在 Elixir 中获得巨大成功。 考虑到这一点,让我们分解问题。

我想遍历my_list

更准确地说,您想对列表中的每个元素执行某些操作并获得结果列表。 那是Enum.map/2

Enum.map(my_list, fn x -> ...)

现在, ...需要替换为我们想要对每个列表元素执行的操作。 我们要获取对应的 map 个元素,忽略那些不存在的。 由于我们要求和,“忽略”实际上只是意味着“替换为零”。 Map.get/3可以从 map 获取一个值,如果没有提供则使用默认值。

Enum.map(my_list, fn x -> Map.get(my_map, x, 0) end)

现在,我们有一个数字列表。 我们只想要总和。 这可以根据Enum.reduce/3来完成,但求和是一项足够常见的任务,它有自己的 function: Enum.sum/1

Enum.sum(Enum.map(my_list, fn x -> Map.get(my_map, x, 0) end))

最后,这是倒着读的。 它说“对列表映射的结果求和”,当它读起来更清晰时“获取列表,从 map 中获取元素,然后求和”。 我们可以用pipe 接线员清理它。 下面的和上面的是等价的。

my_list |> Enum.map(fn x -> Map.get(my_map, x, 0) end) |> Enum.sum

这是一个很好的理解用例:

for key <- my_list, val = my_map[key], reduce: 0 do
  acc -> acc + val
end

这里的val = my_map[key]是一个过滤器。 key不在my_map中时,结果将为nil ,这是一个虚假值,因此被跳过。

虽然这里给出的两个答案都是完全有效的,但为了完整起见,我将使用普通递归发布另一个答案。

defmodule Summer do
  def consume(list, map, acc \\ 0) # head

  def consume([], _, acc), do: acc # exhausted
  def consume([h | t], map, acc) when is_map_key(map, h),
    do: consume(t, map, acc + Map.fetch!(map, h))
  def consume([_h | t], map, acc), do: consume(t, map, acc)
end

Summer.consume my_list, my_map
#⇒ 2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM