【问题标题】:Elixir: Merge list with same map keys to one mapElixir:将具有相同地图键的列表合并到一张地图
【发布时间】:2017-10-04 00:45:49
【问题描述】:

如何在 elixir 中转换此列表

[
%{key1: 1, key2: 2, key3: 3},
%{key1: 4, key2: 5, key3: 6},
%{key1: 7, key2: 8, key3: 9}
]

到这张地图

%{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9])

?

【问题讨论】:

    标签: elixir


    【解决方案1】:

    您可以分两次执行此操作;第一个将所有内容扁平化为一个键值对的一维列表,然后第二个通过键进行分组。

    input = [
      %{key1: 1, key2: 2, key3: 3},
      %{key1: 4, key2: 5, key3: 6},
      %{key1: 7, key2: 8, key3: 9}
    ]
    
    input
    |> Enum.flat_map(fn m -> Map.to_list(m) end) 
    |> Enum.group_by(fn {k, _} -> k end, fn {_, v} -> v end) 
    

    输出

    %{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9]}
    

    【讨论】:

      【解决方案2】:
      Enum.reduce(input, %{key1: [], key2: [], key3: []}, fn m, acc ->
        Map.merge(acc, m, fn _k, v1, v2 -> v1 ++ [v2] end)
      end)
      #⇒ %{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9]}
      

      或者,没有初步的硬编码累加器:

      Enum.reduce(input, %{}, fn m, acc ->
        Map.merge(acc, m, fn
          _k, v1, v2 when is_list(v1) ->
            :lists.reverse([v2 | :lists.reverse(v1)])
          _k, v1, v2 -> [v1, v2]
        end)
      end)
      #⇒ %{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9]}
      

      【讨论】:

        【解决方案3】:

        还不是很擅长 Elixir,但我想出了这个:

        map = Enum.reduce(list, %{}, fn(inner_map, acc) ->
                Map.merge(acc, inner_map, fn(_, v1, v2) ->
                  if is_list(v1) do
                    v1 ++ [v2]
                  else
                    [v1] ++ [v2]
                  end
                end)
              end)
        

        但我认为必须有更优雅的方式来做到这一点

        【讨论】:

        • 最好引入两个带保护的内部函数子句,而不是if
        • @mudasobwa 我会玩弄它
        猜你喜欢
        • 2017-12-25
        • 2022-06-19
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        • 2020-10-19
        • 2021-03-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多