将proplist转换为配对元组

时间:2014-01-17 14:16:35

标签: erlang

这与"Convert tuples to proplists"相反。

我有一个Erlang proplist,可能包含重复键:

P = [{foo, "bar"},             % key = string (char list)
      baz, {quux, true},       % both true; one expanded
      {dog, "Rex"},            % this overrides the duplicate below
      {sum, 42},               % key = integer
      {dog, "Fido"},           % overriden above
      {colour, blue},          % key = atom
      {always, false}].        % opposite of baz or quux

我想把它变成一个配对的元组(适用于bson-erlang),如下所示:

{foo, "bar",
 baz, true,     % atom => {atom, true} => ..., atom, true, ...
 quux, true,
 dog, "Rex",    % the first one.
 sum, 42,
 colour, blue,
 always, false}

所以,[{k1, v1}, {k2, v2}, ...]现在是{k1, v1, k2, v2, ...}

该名单扩大了;重复键使用正确的值(第一个,由proplists:get_value/2返回)。在这种情况下,生成的元组中的键的顺序并不特别重要。

我如何在Erlang中执行此操作?

4 个答案:

答案 0 :(得分:2)

到目前为止,我想出的最好成绩如下:

paired_tuple_from_proplist(P) ->
    % This is a hack, but uses the fact that orddict:from_list
    % removes duplicates. Unfortunately, later overrides earlier
    % which is the other way round from proplists. Hence the reverse.
    D = orddict:from_list(lists:reverse(proplists:unfold(P))),
    L = paired_list_from_orddict(D),
    list_to_tuple(L).

paired_list_from_orddict(D) ->
    paired_list_from_orddict(D, []).

paired_list_from_orddict([], Acc) ->
    Acc;    % DON'T reverse the list.
paired_list_from_orddict([{K,V}|Rest], Acc) ->
    paired_list_from_orddict(Rest, [K,V|Acc]).

答案 1 :(得分:0)

p([{K,V}|T]) -> [K,V|p(T)];
p([S|T]) -> [S,true|p(T)];
p([]) -> [].

答案 2 :(得分:0)

简而言之,但我担心长篇名单效率不高:

5> P = [{foo, "bar"},baz, {quux, true},{dog, "Rex"},{sum, 42},{dog, "Fido"},{colour, blue},{always, false}].

[{foo,"bar"},baz,{quux,true},{dog,"Rex"},{sum,42},{dog,"Fido"},{colour,blue},{always,false}]

6> F = fun({X,Y},{A1,A2}) -> case lists:member(X,A1) of true -> {A1,A2}; _ -> {[X|A1],[X,Y|A2]} end;
          (X,{A1,A2}) -> case lists:member(X,A1) of true -> {A1,A2}; _ ->  {[X|A1],[X,true|A2]} end end.

 #Fun<erl_eval.12.80484245>

7> {_,L2} = lists:foldr(F,{[],[]},P).

{[foo,baz,quux,sum,dog,colour,always],[foo,"bar",baz,true,quux,true,sum,42,dog,"Fido",colour,blue,always,false]}

8> list_to_tuple(L2).

{foo,"bar",baz,true,quux,true,sum,42,dog,"Fido",colour,blue,always,false}

答案 3 :(得分:0)

我想出了这个。

  • 不尊重订单
  • 删除重复的密钥
  • 保留第一个遇到的值
  • 没有hacky东西;)

它只是一个功能!
(把它写成一个单行,可以在lists:foldl/3调用之外定义好玩,以获得更好的格式化。)

toPairedList(ListIn) ->
    ListOut = lists:foldl(fun(Key,Acc) ->
                             [Val|_] = proplists:get_all_values(Key,ListIn),
                             [Key,Val | Acc]
                             end
                          ,[]
                          ,proplists:get_keys(ListIn)),
    list_to_tuple(ListOut).

该死的,我讨厌这些练习,他们正在削弱我的生产力。 仍然是一个较短的变体,使用lists:flatmap/2,因此不再需要累加器。

toPairedList(ListIn) ->
    Job = fun(Key) -> [Val|_] = proplists:get_all_values(Key,ListIn),
                      [Key,Val] end,
    list_to_tuple(lists:flatmap(Job ,proplists:get_keys(ListIn))).

结果:

> toPairedList([{foo, "bar"},baz, {quux, true}, {dog, "Rex"}, {sum, 42}, {dog, "Fido"}, {colour, blue}, {always, false}]).

{colour,blue,always,false,dog,"Rex",quux,true,baz,true,sum,42,foo,"bar"}