gpt4 book ai didi

elixir - 展平/合并嵌套 map

转载 作者:行者123 更新时间:2023-12-02 01:04:23 31 4
gpt4 key购买 nike

假设我们有这样的 map :

%{"a": %{"b": 2, "c":5}, "d": 1}

有没有类似this function的东西(js回答同一问题)内置elixr?

最终结果应该是:

%{"a.b": 4, "a.c":5, "d": 1}

最佳答案

由于我已经多次完成此任务,并且我自己需要它,因此我创建了十六进制包 iteraptor为此:

将其添加到 mix.exs 中的依赖项列表中:

def deps do
[{:iteraptor, "~> 1.13"}]
end

并像这样使用它:

iex(1)> %{a: %{b: 2, c: 5}, d: 1} |> Iteraptor.to_flatmap
%{"a.b": 2, "a.c": 5, d: 1}

它支持无限嵌套以及maplist

各部分代码如下:

    defmodule Iteraptor do
@joiner "."

@doc """
iex> [:a, 42] |> Iteraptor.to_flatmap
%{"0": :a, "1": 42}

iex> %{a: 42} |> Iteraptor.to_flatmap
%{a: 42}

iex> %{a: 42, b: 42} |> Iteraptor.to_flatmap
%{a: 42, b: 42}

iex> %{a: %{b: 42}, d: 42} |> Iteraptor.to_flatmap
%{"a.b": 42, d: 42}

iex> %{a: [:b, 42], d: 42} |> Iteraptor.to_flatmap
%{"a.0": :b, "a.1": 42, d: 42}

iex> %{a: %{b: [:c, 42]}, d: 42} |> Iteraptor.to_flatmap
%{"a.b.0": :c, "a.b.1": 42, d: 42}

iex> %{a: %{b: 42}} |> Iteraptor.to_flatmap
%{"a.b": 42}

iex> %{a: %{b: %{c: 42}}} |> Iteraptor.to_flatmap
%{"a.b.c": 42}

iex> %{a: %{b: %{c: 42}}, d: 42} |> Iteraptor.to_flatmap
%{"a.b.c": 42, d: 42}

iex> %{a: %{b: %{c: 42, d: [nil, 42]}, e: [:f, 42]}} |> Iteraptor.to_flatmap
%{"a.b.c": 42, "a.b.d.0": nil, "a.b.d.1": 42, "a.e.0": :f, "a.e.1": 42}
"""

def to_flatmap(input, joiner \\ @joiner) when is_map(input) or is_list(input) do
process(input, joiner)
end

@doc """
iex> %{a: %{b: %{c: 42}}} |> Iteraptor.each(fn {k, v} -> IO.inspect({k, v}) end)
%{"a.b.c": 42}
"""
def each(input, joiner \\ @joiner, fun) do
unless is_function(fun, 1), do: raise "Function or arity fun/1 is required"
process(input, joiner, "", %{}, fun)
end

defp process(input, joiner, prefix \\ "", acc \\ %{}, fun \\ nil)

defp process(input, joiner, prefix, acc, fun) when is_map(input) do
input |> Enum.reduce(acc, fn({k, v}, memo) ->
prefix = join(prefix, k, joiner)
if is_map(v) or is_list(v) do
process(v, joiner, prefix, memo, fun)
else
unless is_nil(fun), do: fun.({prefix, v})
Map.put memo, prefix, v
end
end)
end

defp process(input, joiner, prefix, acc, fun) when is_list(input) do
input
|> Enum.with_index
|> Enum.map(fn({k, v}) -> {v, k} end)
|> Enum.into(%{})
|> process(joiner, prefix, acc, fun)
end

defp join(l, "", _) do
String.to_atom(to_string(l))
end

defp join("", r, _) do
String.to_atom(to_string(r))
end

defp join(l, r, joiner) do
String.to_atom(to_string(l) <> joiner <> to_string(r))
end
end

关于elixir - 展平/合并嵌套 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39401947/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com