【问题标题】:Pattern matching map with exact list of keys具有精确键列表的模式匹配映射
【发布时间】:2018-11-14 14:56:43
【问题描述】:

为了验证一些 JSON 文档,我需要确保我的 JSON(表示有一个映射)具有一组特定的字段,不多也不少。

据我所知,与#{a := FieldA} = MyJSON 之类的模式匹配只能确保密钥a 存在于MyJSON 中。 不幸的是,maps:with/2 会忽略丢失的键,而大多数其他地图功能当时只能在单个键上工作。

在这种情况下,确保地图包含特定字段或字段列表而不包含任何其他字段的推荐方法是什么?

我目前的丑陋解决方案是对我需要的所有键进行模式匹配并重建一个新映射,如下所示:

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

但它变得非常难以维护,而且很快。

【问题讨论】:

  • 在这些情况下使用record 不是更好吗?或者至少一个记录/元组(或任何其他你事先知道它的结构)你可以检查它。
  • @ɐuıɥɔɐɯ 我可能会使用 proplist 或元组(这是 sile/jsone 的输出选项)。但是比较两个地图的完全相同的键是一个常见的用例,而且由于尚未实现所有地图功能,我认为它最终会在匹配语法或地图模块中得到支持。

标签: erlang pattern-matching


【解决方案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>

【讨论】:

    【解决方案2】:

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

    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的大小以快速失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-20
      • 2012-01-25
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 2016-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多