Elixir Today: 특정 필드를 통해 맵 목록 결합

참조



references

소개



최근에 How to combine a list of map via specific field 에 대한 비슷한 질문에 대해 작업했습니다.

나는 엘릭서 포럼을 보았고 기꺼이 무언가를 찾았습니다. 답변 중 하나가 Enum.group_by + Enum.map 을 사용하는 것을 보았습니다.

내 호기심을 감안할 때 How can I come up with a solution using Enum.reduce ?

호기심 발동



그래서 Enum.reduce를 사용하여 운동을 시작했습니다.


 @list [
    %{id: 1, list: [1]},
    %{id: 1, list: [2]},
    %{id: 2, list: [1]},
    %{id: 3, list: [1]},
    %{id: 1, list: [3, 4, 5]},
    %{id: 2, list: [2, 3]},
    %{id: 3, list: [2, 3, 4, 5]},
    %{id: 4, list: [2, 3, 4, 5]},
    %{id: 4, list: [1]}
  ]

    @list
    |> Enum.reverse()
    |> Enum.reduce(%{}, fn %{id: id, list: _list} = f, acc ->
      case acc do
        %{^id => existing} -> Map.put(acc, id, [f | existing])
        %{} -> Map.put(acc, id, [f])
      end
    end)
    |> Enum.map(fn {id, list} -> %{id: id, list: Enum.flat_map(list, & &1.list)} end)



  • 이런 식으로 특정 ID와 해당 목록으로 샘플 목록을 만들었습니다.
  • 목록의 순서를 반대로 한다
  • Enum.reduce를 사용하여 그에 따라 ID 목록을 정렬하고 결합했습니다.
  • 마지막으로 Enum.map를 사용하여 데이터를 변환합니다.

  • 벤치마킹!


    group_byreduce 를 사용한 결과를 비교하기 시작했습니다. 이를 위해 Benchee 을 사용했습니다.

    설치하려면 종속 항목에 benchee를 추가하세요.

    {:benchee, "~> 1.0", only: :dev}
    


    주어진 설정

     @list [
        %{id: 1, list: [1]},
        %{id: 1, list: [2]},
        %{id: 2, list: [1]},
        %{id: 3, list: [1]},
        %{id: 1, list: [3, 4, 5]},
        %{id: 2, list: [2, 3]},
        %{id: 3, list: [2, 3, 4, 5]},
        %{id: 4, list: [2, 3, 4, 5]},
        %{id: 4, list: [1]}
      ]
    
    def groupby(list) do
        Enum.group_by(list, & &1.id)
        |> Enum.map(fn {id, list} -> %{id: id, list: Enum.flat_map(list, & &1.list)} end)
    end
    
    def reduce(list) do
        list
        |> Enum.reverse()
        |> Enum.reduce(%{}, fn %{id: id, list: _list} = f, acc ->
          case acc do
            %{^id => existing} -> Map.put(acc, id, [f | existing])
            %{} -> Map.put(acc, id, [f])
          end
        end)
        |> Enum.map(fn {id, list} -> %{id: id, list: Enum.flat_map(list, & &1.list)} end)
    end
    
    


    그런 다음 실행

    Benchee.run(
       %{
            "groupby_enum_map" => fn -> PracticeElixir.groupby(@list) end,
            "reduce_enum_map" => fn -> PracticeElixir.reduce(@list) end
          },
          print: [fast_warning: false]
    )
    
    


    벤치마크 결과



    내 개발 환경을 감안할 때 결과는 다음과 같습니다.

    available_memory: "16 GB",
    cpu_speed: "Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz",
    elixir: "1.12.3",
    erlang: "24.0.6",
    num_cores: 16,
    os: :macOS
    



    Benchmark suite executing with the following configuration:
    warmup: 2 s
    time: 5 s
    memory time: 0 ns
    reduction time: 0 ns
    parallel: 1
    inputs: none specified
    Estimated total run time: 14 s
    
    Benchmarking groupby_enum_map ...
    Benchmarking reduce_enum_map ...
    
    Name                       ips        average  deviation         median         99th %
    reduce_enum_map         1.08 M        0.93 μs   ±208.21%        0.80 μs           5 μs
    groupby_enum_map        0.97 M        1.03 μs   ±251.03%        0.90 μs           4 μs
    
    Comparison:
    reduce_enum_map         1.08 M
    groupby_enum_map        0.97 M - 1.12x slower +0.109 μs
    
    


    전체 구현을 볼 수 있습니다here!.

    Happy Coding!

    좋은 웹페이지 즐겨찾기