Erlang 替换嵌套映射中的键

Erlang 替换嵌套映射中的键,erlang,maps,Erlang,Maps,如何在不知道路径(或替换与模式匹配的键)的情况下,用另一个键替换嵌套贴图中的所有键,例如: Map = #{foo => #{bar => 1, foo => #{bar => 2}}}. Map2 = maps:keyreplace(bar, foo, Map). >>> #{foo => #{foo => 1, foo => #{foo => 2}}} 最有效的方法是什么? 在平面地图中替换关键点似乎非常简单: keyrep

如何在不知道路径(或替换与模式匹配的键)的情况下,用另一个键替换嵌套贴图中的所有键,例如:

Map = #{foo => #{bar => 1, foo => #{bar => 2}}}.
Map2 = maps:keyreplace(bar, foo, Map).
>>> #{foo => #{foo => 1, foo => #{foo => 2}}}
最有效的方法是什么?
在平面地图中替换关键点似乎非常简单:

keyreplace(K1, K2, M) when is_map(M) ->
    case maps:take(K1, M) of
        {V, M2} ->
            maps:put(K2, V, M2);
        error -> M
    end.
或者像这样,也许:

keymap(F, Map) ->
    maps:fold(fun(K, V, Acc) ->
        maps:put(F(K), V, Acc)
    end, #{}, Map).
Map = #{foo => 1, bar => 2}.
Fun = fun(K) -> atom_to_list(K) end.
Map2 = keymap(Fun, Map).
>>> #{"bar" => 2,"foo" => 1}

我编写了递归函数,您可以使用它来实现您的目标,它需要3个参数:

Is_matched-检查键是否与模式匹配的函数

Convert-根据需要转换密钥的函数

映射-映射到进程

replace_keys(Is_matched, Convert, Map) when is_map(Map) ->
  maps:fold(fun (K, V, AccIn) ->
    NewKey =
      case Is_matched(K) of
        true -> Convert(K);
        false -> K
      end,
    maps:put(NewKey, replace_keys(Is_matched, Convert, V), AccIn)
  end, #{}, Map);

replace_keys(_, _, Term) -> Term. 
例如:

1> Map = #{a => "1", <<"b">> => #{c => "2", <<"d">> => 3}}.            
#{a => "1",<<"b">> => #{c => "2",<<"d">> => 3}}
2> Is_matched = fun(Term) -> is_atom(Term) end.
#Fun<erl_eval.6.99386804>
3> Convert = fun(Term) -> atom_to_list(Term) end.
#Fun<erl_eval.6.99386804>
4> keyreplace:replace_keys(Is_matched, Convert, Map).
#{"a" => "1",<<"b">> => #{"c" => "2",<<"d">> => 3}}
1>Map={a=>1',=>c=>2',=>3}。
#{a=>“1”、=>{c=>“2”、=>3}
2> Is_matched=fun(Term)->Is_atom(Term)end。
#乐趣
3> Convert=fun(术语)->atom\u to\u列表(术语)结束。
#乐趣
4> 键替换:替换键(匹配、转换、映射)。
#{“a”=>“1”、=>{“c”=>“2”、=>3}

这可以通过对
贴图:折叠进行一些修改来完成:

  • 如果第三个参数不是映射,则按原样返回它
  • 折叠时:
  • 使用value字段递归调用函数以获取新值
  • 如果键与K1匹配,则将新值放入K2
  • 您的示例输出不正确-它有两个
    foo
    键的值。我在下面的测试中修改了它

    keyreplace(K1, K2, Map) when is_map(Map) ->
      maps:fold(fun(K, V, Acc) ->
        Key = if K == K1 -> K2; true -> K end,
        Value = keyreplace(K1, K2, V),
        maps:put(Key, Value, Acc)
      end, #{}, Map);
    keyreplace(_K1, _K2, Term) -> Term.
    
    1> c(a).
    {ok,a}
    2> Map = #{foo => #{bar => 1, baz => #{bar => 2}}}.
    #{foo => #{bar => 1,baz => #{bar => 2}}}
    3> a:keyreplace(bar, foo, Map).
    #{foo => #{baz => #{foo => 2},foo => 1}}