如何映射地图列表并添加它们?

how to map over the list of map and add them?

我有一个类似这样的地图列表

    iex(84)> a                                                            
[
  %{a: 1, b: 2, c: [%{x: 1, y: 2}, %{x: 2, y: 3}]},
  %{a: 3, b: 4, c: [%{x: 2, y: 3}, %{x: 2, y: 3}]},
  %{a: 5, b: 6, c: [%{x: 3, y: 4}, %{x: 3, y: 4}]}
]

我正在尝试获得这样的结果

  [
  %{a: 1, b: 2, c: 8},
  %{a: 3, b: 4, c: 10},
  %{a: 5, b: 6, c: 14}
]

无法映射“c”的值,如果我这样做,我将丢失初始映射。我该怎么办?

在输入中我们应该修改深层嵌套的元素。有一种最被低估的处理方式:Access.

input = [
  %{a: 1, b: 2, c: [%{x: 1, y: 2}, %{x: 2, y: 3}]},
  %{a: 3, b: 4, c: [%{x: 2, y: 3}, %{x: 2, y: 3}]},
  %{a: 5, b: 6, c: [%{x: 3, y: 4}, %{x: 3, y: 4}]}
]

这里我们将修改输入的所有元素,更新 :c。所以我们需要到达 [Access.all(), :c] 并在他们身上调用 update_in/3

update_in(input, [Access.all(), :c], fn x ->
  Enum.reduce(x, 0, & &2 + (&1 |> Map.values() |> Enum.sum()))
end)
#⇒ [%{a: 1, b: 2, c: 8},
#   %{a: 3, b: 4, c: 10},
#   %{a: 5, b: 6, c: 14}]

我相信内部求和可以以更优雅的方式完成,但这不是重点。重点是:在此处使用 Access(实际上在任何对嵌套枚举进行操作的地方。)

您可以使用带有地图更新语法的 for/1 来替换 c 键:

input = [
  %{a: 1, b: 2, c: [%{x: 1, y: 2}, %{x: 2, y: 3}]},
  %{a: 3, b: 4, c: [%{x: 2, y: 3}, %{x: 2, y: 3}]},
  %{a: 5, b: 6, c: [%{x: 3, y: 4}, %{x: 3, y: 4}]}
]

for map <- input do
  %{map | c: Enum.flat_map(map.c, &Map.values/1) |> Enum.sum()}
end

输出:

[%{a: 1, b: 2, c: 8}, %{a: 3, b: 4, c: 10}, %{a: 5, b: 6, c: 14}]