Elixir의 지도를 완전 병합
19596 단어 40代駆け出しエンジニアelixiradventcalendar2022
はじめに
たまたまあるElixirのソースコードを読んでいたらdeep mergeしてたので面白いな〜と思い調べるに至りました.
Elixir標準의 Map.merge/2
https://hexdocs.pm/elixir/Map.html#merge/3
Elixir는 言語には標準の
Map.merge/2
가 가능합니다.%{a: 1} |> Map.merge(%{b: 2}) |> Map.merge(%{c: 3})
# %{a: 1, b: 2, c: 3}
しかしながら、Mapの構造が入れ子になっている場合、再帰的に統合することはしてくれません.
entry1 = %{"a" => %{"b" => %{"c1" => "hello", "c2" => "world" }}}
entry2 = %{"a" => %{"b" => %{"c1" => "コンニチハ", "c2" => "セカイ" }}}
entry3 = %{"a" => %{"b" => %{"c3" => "elixir" }}}
entry1 |> Map.merge(entry2) |> Map.merge(entry3)
# %{"a" => %{"b" => %{"c3" => "elixir"}}}
欲しい結果が以下のようなものである場合、悩まされるかもしれません.
%{
"a" => %{
"b" => %{"c1" => "コンニチハ", "c2" => "セカイ", "c3" => "elixir"}
}
}
そこで登場するのが
deep_merge
입니다.やり方はいくつか考えられます.
deep_merge (A)
今回の調査のきっかけとなった実装입니다.
https://github.com/fhunleth/beam_benchmarks/blob/6f970bff5b9291ffe2ddc849afbeabeea6595baf/lib/beam_benchmarks/info.ex#L89
defmodule MapUtils1 do
def deep_merge(map1, map2) when is_map(map1) and is_map(map2) do
Map.merge(map1, map2, fn _key, value1, value2 -> deep_merge(value1, value2) end)
end
def deep_merge(not_map1, not_map2), do: not_map2
end
entry1 |> MapUtils1.deep_merge(entry2) |> MapUtils1.deep_merge(entry3)
deep_merge (비)
nettで調べて出てきたのがこれです.
https://stackoverflow.com/questions/38864001/elixir-how-to-deep-merge-maps/38865647#38865647
defmodule MapUtils2 do
def deep_merge(left, right) do
Map.merge(left, right, &deep_resolve/3)
end
defp deep_resolve(_key, left = %{}, right = %{}) do
deep_merge(left, right)
end
defp deep_resolve(_key, _left, right) do
right
end
end
entry1 |> MapUtils2.deep_merge(entry2) |> MapUtils2.deep_merge(entry3)
deep_merge (C)
deep_merge
を書きました. defmodule MapUtils3 do
def deep_merge(left, right) do
Map.merge(left, right, fn
_key, l = %{}, r = %{} -> deep_merge(l, r)
_key, _l, r -> r
end)
end
end
entry1 |> MapUtils3.deep_merge(entry2) |> MapUtils3.deep_merge(entry3)
deep_merge ( 키워드 型)
Config
モジュールの内部に Keyword
型の設定データーを deep_merge
する __merge__/2
그렇담 関数がありました. deep_merge
を Keyword
型に対して実施したい場合に参考になるかもしれません. https://github.com/elixir-lang/elixir/blob/6764de46cbd21003c54a0072cc3b9a6d9dffea16/lib/elixir/lib/config.ex#L328-L340
deep_merge ( 키워드 型와 지도 型両方)
Map
型と Keyword
型の両方に対応する こともできそうです.defmodule MapUtils5 do
def deep_merge(map1, map2) when is_map(map1) and is_map(map2) do
Map.merge(map1, map2, fn _key, value1, value2 -> deep_merge(value1, value2) end)
end
def deep_merge(kw1, kw2) when is_list(kw1) and is_list(kw2) do
Keyword.merge(kw1, kw2, fn _key, value1, value2 -> deep_merge(value1, value2) end)
end
def deep_merge(_not_map1, not_map2), do: not_map2
end
# Map
entry1 = %{"a" => %{"b" => %{"c1" => "hello", "c2" => "world" }}}
entry2 = %{"a" => %{"b" => %{"c1" => "コンニチハ", "c2" => "セカイ" }}}
entry3 = %{"a" => %{"b" => %{"c3" => "elixir" }}}
entry1 |> MapUtils5.deep_merge(entry2) |> MapUtils5.deep_merge(entry3)
# Keyword
entry1 = [a: [b: [c1: "hello", c2: "world" ]]]
entry2 = [a: [b: [c1: "コンニチハ", c2: "セカイ" ]]]
entry3 = [a: [b: [c3: "elixir" ]]]
entry1 |> MapUtils5.deep_merge(entry2) |> MapUtils5.deep_merge(entry3)
deep_merge (헥스팍케이지)
deep_merge
関連の色んな機能がHexpacke-jiにされています. https://github.com/PragTob/deep_merge
iex
Mix.install([:deep_merge])
entry1 |> DeepMerge.deep_merge(entry2) |> DeepMerge.deep_merge(entry3)
さいごに
Elixir를 楽しみましょう!
https://qiita.com/piacerex/items/e5590fa287d3c89eeebf
https://qiita.com/torifukukaiou/items/1edb3e961acf002478fd
各コMUNITIの詳細は、「ElixirコMUNITIの歩き方 -国内온라인編-」をご覧ください
各種Elixiribent の開催予定は、「Elixirivevent カレンダー」から確認/参加できます 📆
Reference
이 문제에 관하여(Elixir의 지도를 완전 병합), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mnishiguchi/elixirnomapwodeep-merge-33d5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)