替换嵌套映射中的键

时间:2017-12-12 13:13:56

标签: erlang maps

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

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}

或者那样,也许:

b.func

2 个答案:

答案 0 :(得分:3)

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

Is_matched - 用于检查该键是否与您的模式匹配的函数。

转换 - 根据需要转换键的函数。

地图 - 地图处理。

package org.leiroc.data.schema.leidata._2014;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "LEIRecordType", propOrder = {"lei", "entity", "registration", "nextVersion", "extension"})
public class LEIRecordType {

    @XmlElement(name = "LEI", required = true)
    protected String lei;

    @XmlElement(name = "Entity", required = true)
    protected EntityType entity;

    @XmlElement(name = "Registration", required = true)
    protected RegistrationType registration;

    @XmlElement(name = "NextVersion")
    protected LEIRecordNextVersionType nextVersion;

    @XmlElement(name = "Extension")
    protected ExtensionType extension;

    public String getLEI() {
        return this.lei;
    }

    public void setLEI(String paramString) {
        this.lei = paramString;
    }

    public EntityType getEntity() {
        return this.entity;
    }

    public void setEntity(EntityType paramEntityType) {
        this.entity = paramEntityType;
    }

    public RegistrationType getRegistration() {
        return this.registration;
    }

    public void setRegistration(RegistrationType paramRegistrationType) {
        this.registration = paramRegistrationType;
    }

    public LEIRecordNextVersionType getNextVersion() {
        return this.nextVersion;
    }

    public void setNextVersion(LEIRecordNextVersionType paramLEIRecordNextVersionType) {
        this.nextVersion = paramLEIRecordNextVersionType;
    }

    public ExtensionType getExtension() {
        return this.extension;
    }

    public void setExtension(ExtensionType paramExtensionType) {
        this.extension = paramExtensionType;
    }
}

示例:

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 :(得分:3)

这可以通过对maps:fold尝试的一些修改来完成:

  1. 如果第三个参数不是地图,请按原样返回。
  2. 折叠时:
    1. 使用value字段递归调用函数以获取新值。
    2. 如果密钥与K1匹配,请将新值放入K2。
  3. 您的示例输出不正确 - 它有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}}