模式匹配地图与确切的键列表

时间:2018-06-05 07:41:55

标签: erlang pattern-matching

为了验证一些JSON文档,我需要确保我的JSON(表示有一个地图)具有一组特定的字段,而不是更少。

据我所知,模式与#{a := FieldA} = MyJSON之类的匹配仅确保a中存在关键MyJSON。 不幸的是,maps:with/2忽略了丢失的密钥,而且大多数其他映射函数当时都在单个密钥上工作。

在这种情况下,建议哪种方法可以确保地图包含特定字段或字段列表而不包含任何其他字段?

我当前的,丑陋的解决方案是模式匹配我需要的所有键并重建一个新的地图,如:

validate(#{a := A, b := B, c := C}) ->
#{a => A, b => B, c => C}.

但很快就很难维持。

2 个答案:

答案 0 :(得分:1)

如果我理解你的问题,这段代码应该做你想要的:

is_map_valid(Map,SortedKeyList) ->
    SortedKeyList == lists:sort(maps:keys(Map)).

在shell中测试:

1> Is_map_valid = fun(Map,SortedKeyList) -> SortedKeyList == lists:sort(maps:keys(Map)) end.
#Fun<erl_eval.12.99386804>
2> Map1 = #{a => 1, b => 2}.                                                                
#{a => 1,b => 2}
3> Map2 = #{a => 1, b => 2, c => 3}.
#{a => 1,b => 2,c => 3}
4> Map3 = #{a => 1, b => 2, c => 3, d => 4}.
#{a => 1,b => 2,c => 3,d => 4}
5> Keys = [a,b,c].
[a,b,c]
6> Is_map_valid(Map1,Keys).
false
7> Is_map_valid(Map2,Keys).
true
8> Is_map_valid(Map3,Keys).
false
9>

答案 1 :(得分:0)

如果我理解正确:在maps:size之后使用erlang:map_size(或maps:with,如果您需要保护条件),例如

validate(Keys, Map) -> 
    ExpectedSize = erlang:length(Keys),
    case maps:with(Keys, Map) of
        Map1 when erlang:map_size(Map1) == ExpectedSize -> {ok, Map1};
        _ -> invalid
    end.

您还可以先检查Map尺寸,然后快速失败。