erlang:从PropList中获取键集的值
我有“难”的道具清单。我需要进入erlang:从PropList中获取键集的值,list,loops,search,erlang,List,Loops,Search,Erlang,我有“难”的道具清单。我需要进入serviceCatalog并遍历它的所有值,直到得到一个名为me J =[{<<"access">>, {[{<<"token">>, {[{<<"issued_at">>,<<"2015-09-12T13:27:38.789879">>}, {<<"expires">>,<<"2
serviceCatalog
并遍历它的所有值,直到得到一个名为me
J =[{<<"access">>,
{[{<<"token">>,
{[{<<"issued_at">>,<<"2015-09-12T13:27:38.789879">>},
{<<"expires">>,<<"2015-09-12T14:27:38Z">>},
{<<"id">>,<<"fe">>},
{<<"tenant">>,
{[{<<"description">>,null},
{<<"enabled">>,true},
{<<"id">>,<<"01">>},
{<<"name">>,<<"service">>}]}},
{<<"audit_ids">>,[<<"f">>]}]}},
{<<"serviceCatalog">>,
[{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"http://8.198.99.999:8080">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,
<<"http://8.198.99.999:8080/v1/AUTH_01a"...>>},
{<<"id">>,<<"30">>},
{<<"publicURL">>,<<"8.198.99.999:8080/v1/"...>>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"object-store">>},
{<<"name">>,<<"my">>}]},
{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"id">>,<<"4b3f44a5c64b4bd8b10c376c858b"...>>},
{<<"publicURL">>,<<"8.198.99.999:8080"...>>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"identity">>},
{<<"name">>,<<"other">>}]}]},
{<<"user">>,
{[{<<"username">>,<<"my">>},
{<<"roles_links">>,[]},
{<<"id">>,<<"8">>},
{<<"roles">>,[{[{<<"name">>,<<"admin">>}]}]},
{<<"name">>,<<"me">>}]}},
{<<"metadata">>,
{[{<<"is_admin">>,0},
{<<"roles">>,
[<<"e">>]}]}}]}}]
J=[{,
{[{,
{[{,},
{,},
{,},
{,
{[{,null},
{,没错},
{,},
{,}]}},
{,[]}]}},
{,
[{[{,
[{[{,},
{,},
{,
},
{,},
{,}]}]},
{,[]},
{,},
{,}]},
{[{,
[{[{,},
{,},
{,},
{,},
{,}]}]},
{,[]},
{,},
{,}]}]},
{,
{[{,},
{,[]},
{,},
{,[{[{,}]}]},
{,}]}},
{,
{[{,0},
{,
[]}]}}]}}]
我正在寻找一种很好的方法。
我是这样开始实施的(但看起来还有更优雅的解决方案):
A1=proplist:get_值(,J)。
A=元件(1,A1)。
B=proplist:get_值(,A)。
C=元素(1,B)。
D=proplist:get_值(,C)。
任何建议都是好的考虑到数据嵌套的深度,一种方法是编写一组递归函数子句,可以找到具有给定键的2元组,而不管其在数据中的级别如何。下面是一个例子:
-module(t).
-export([extract/2]).
extract(Key, Data) ->
extract(Key, Data, []).
extract(_Key, [], Acc) ->
Acc;
extract(Key, {Key,_}=KV, Acc) ->
[KV|Acc];
extract(Key, [{Key,_}=KV|Fields], Acc) ->
extract(Key, Fields, [KV|Acc]);
extract(Key, [{_,V}|Fields], Acc) when is_tuple(V); is_list(V) ->
extract(Key, Fields, extract(Key, V, Acc));
extract(Key, Data, Acc) when is_list(Data) ->
lists:foldl(fun(V, FoldAcc) when is_tuple(V); is_list(V) ->
extract(Key, V, FoldAcc);
(_, FoldAcc) ->
FoldAcc
end, Acc, Data);
extract(Key, Data, Acc) when is_tuple(Data) ->
extract(Key, tuple_to_list(Data), Acc).
extract/2
函数只是将其参数和空累加器列表一起传递给extract/3
。extract/3
的条款如下所述:
- 第一个子句检查数据是否为空列表,如果为空,则返回累加器
- 第二个子句匹配所需的
,作为2元组的第一个元素,并将匹配的元组添加到累加器中键
- 第三个子句匹配所需的
,作为列表开头2元组的第一个元素。它将匹配的元组添加到累加器中,并继续从列表的其他元素中提取键
- 第四个子句处理2元组的情况,其中元组中的值要么是列表,要么是元组;如果是,它将尝试从值中提取,然后继续从列表的其余部分提取
- 当
是一个与前面的子句已经匹配的列表不匹配的列表时,第五个子句匹配。它折叠列表的所有值,尝试从所有嵌套列表和元组值中提取,并忽略所有其他值Data
- 当
是元组时,第六个也是最后一个子句匹配;它只是将元组转换为一个列表,并递归调用Data
extract/3
J
,我们可以找到一个具有
键的2元组,如下所示:
1> SCs = t:extract(<<"serviceCatalog">>, J).
[{<<"serviceCatalog">>,
[{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"http://8.198.99.999:8080">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,
<<"http://8.198.99.999:8080/v1/AUTH_01a">>},
{<<"id">>,<<"30">>},
{<<"publicURL">>,<<"8.198.99.999:8080/v1/">>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"object-store">>},
{<<"name">>,<<"my">>}]},
{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"id">>,<<"4b3f44a5c64b4bd8b10c376c858b">>},
{<<"publicURL">>,<<"8.198.99.999:8080">>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"identity">>},
{<<"name">>,<<"other">>}]}]}]
列表理解遍历所有
元素,从每个元素中提取所有
元组,并检查是否有值为
的元组
不幸的是,示例数据中的
元素没有问题中描述的{,}
元组,因此上述列表理解结果(结果未显示)中的布尔值为false
。但是,无论哪种方式,要遍历列表理解的结果,只保留true
值,但去掉布尔值,这样生成的列表只包含匹配的
元素,我们可以折叠列表。首先,让我们制作一个折叠函数:
3> Fold = fun({SC, true}, Acc) -> [SC|Acc]; (_, Acc) -> Acc end.
#Fun<erl_eval.12.54118792>
同样,由于数据中没有
元素包含{,}
元组,因此这里的结果列表是空的,但是如果有,我们将从列表返回它们的值:foldl/3
请澄清问题;您的意思是要查找此数据中具有键
的所有元组,该键的值包含一个值为{,}
的元组,如果找到{,}
,是否要返回整个
元组?顺便说一句,如果这是您想要的,请注意您的示例数据不匹配,因为{,}
仅存在于{,…}
元组中。
2> [{SC,lists:any(fun({_, V}) -> V == <<"me">> end, t:extract(<<"name">>, SC))} || SC <- SCs].
3> Fold = fun({SC, true}, Acc) -> [SC|Acc]; (_, Acc) -> Acc end.
#Fun<erl_eval.12.54118792>
4> SCBools = [{SC,lists:any(fun({_, V}) -> V == <<"me">> end, t:extract(<<"name">>, SC))} || SC <- SCs].
...
5> lists:foldl(Fold, [], SCBools).
[]