如何将可枚举累加到类别中,每个类别都有累加值?

How to accumulate the enumerable into the categories with accumulated value for each category?

如何将元组列表缩减为每个类别的总和列表?

l = [{:a, 3}, {:b, 5}, {:c, 3}, {:a, 6}, {:b, 3}, {:a, 3}] 
sum_by_category = ...reduce_by... 
sum_by_category = [{:a, 12},{:b, 8},{:c, 3}]

应该是类似reduce_by(enumerable, acc, accumulation_fun, key_fun)的函数 其中

  1. "acc" 和 "accumulation_fun" 的工作方式与 Enum.reduce 和

    类似
  2. "key_fun" 的工作方式类似于 Enum.group_by.

虽然您可以使用 Enum.group_by/3 来获得更有条理的枚举,但您仍然必须遍历结果列表,所以我认为这里最有效的解决方案是使用简陋的 Enum.reduce/3

l = [{:a, 3}, {:b, 5}, {:c, 3}, {:a, 6}, {:b, 3}, {:a, 3}]


summed = Enum.reduce(l, %{}, fn {k, v}, acc ->
  existing = Map.get(acc, k, 0)
  Map.put(acc, k, existing + v)
end)
IO.inspect(summed)
# yields:
# %{a: 12, b: 8, c: 3}

如果需要,使用 Enum.to_list/1 将结果转换回关键字列表。

或者您可以使用 for with reduce 选项:

for {e, n} <- l, reduce: [] do
  acc -> Keyword.update(acc, e, n, &(&1 + n))
end

经过一番探索,我找到了方法(两种变体):

l = [{:a, 3}, {:b, 5}, {:c, 3}, {:a, 6}, {:b, 3}, {:a, 3}]

l |> Enum.group_by(fn {key, _value}-> key end)
  |> Enum.map( fn {group, value_list} -> {group, Enum.reduce(value_list, 0, fn {_key,value}, acc -> acc + value end)} end)

l |> Enum.group_by(fn {key, _value}-> key end, fn {_key, value}-> value end)
  |> Enum.map( fn {group, value_list} -> {group, Enum.reduce(value_list, 0, fn value, acc -> acc + value end)} end)

两种方式的结果相同。然而,第一个更好地举例说明了可以根据输入数据定义什么是类别,后者还展示了如何在累积之前处理原始 l 列表中的值。

希望这对其他人有帮助。