2017-12-12 19 views
2

をキーに置き換えます。例えば、ネストされたマップでは、私はパスを知らなくても、他のキーとネストされたマップ内のすべてのキーを交換する(またはパターンに一致するキーを、交換する)ことができますどのように

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

私はあなたがあなたの目標を達成するために使用することができ再帰関数を書いて、それが3を取ります引数:

Is_matched - あなたのパターンに一致するキーをチェックする関数です。

変換 - 必要に応じてキーを変換します。

マップ - 処理するマップ。

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}} 
4

これはあなたのmaps:fold試みにいくつかの変更を行うことができます。3番目の引数がマップされていない場合

  1. 、あるとしてそれを返します。
  2. 折りたたみ時:
    1. を再帰的に新しい価値を得るために、値フィールドで関数を呼び出します。
    2. キーがK1と一致する場合は、新しい値をK2に入れます。

あなたの出力例が正しくありません - それはfooキーの2つの値を持っています。私は以下のテストでそれを修正しました。

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}} 
関連する問題