查找任意项中出现的所有元组

时间:2019-06-20 11:40:10

标签: erlang

我有一个任意术语,其中包含未知的结构良好的erlang数据。我需要在此术语中的任何位置找到元组{atom,_}的所有出现。

模式匹配依赖于知道哪个结构包含您的数据,但我不知道。

我需要从中提取示例

  [
    {description, ""},
    {applications, [
      kernel,
      stdlib,
      ssl
    ]},
    {env, [
      {is_enabled, true},
      {jos, {atom, "2o3urglk3ugr"}},
      {fss_pool, {
        [
          {ja, 10}
        ],
        [
          {host, {atom, "fkejbkjfb"}},
          {port, 6000}
        ]}
      }
    ]}
  ]}.

是否有通用的模式匹配方式来遍历任意项?

2 个答案:

答案 0 :(得分:4)

不是。您必须特别对待要遍历的每种数据结构。像这样:

traverse({atom, Value}) ->
    %% found it!
    [{atom, Value}];
traverse(List) when is_list(List) ->
    lists:flatmap(fun traverse/1, List);
traverse(Tuple) when is_tuple(Tuple) ->
    lists:flatmap(fun traverse/1, tuple_to_list(Tuple));
traverse(Map) when is_map(Map) ->
    lists:flatmap(fun traverse/1, maps:to_list(Map));
traverse(_Other) ->
    %% not the value we're looking for
    [].

答案 1 :(得分:-2)

这不是一个完整的答案,因为我刚刚安装了OTP 22.0,但是您可以将上述值转换​​为二进制值,然后使用RE查找所有必需的匹配项。

例如:

X = ...,
B  = term_to_binary(X),
{ok, MP} = re:compile(<<"atom">>, [extended]),
{match, Res} = re:run(B, MP, [{capture, all, index}]),
ok = io:fwrite("BX: ~p ~p~n ~p", [B, MP, Res]).

re:compile和re:run的选项并不完全符合您的要求,正则表达式本身应扩展为包含原子后面的值:/

(由于时间限制,我无法提供复制和粘贴的答案,但是我做了一些类似于从另一个程序解析文本日志并找到所需内容的操作。希望这指向另一个可选的解决方法。)