我有一个列表 L
L = [L1, L2, L3,...].
其中L1,L2,L3 ..本身就是列表,如下所示:
L1 = [{k1, 10}, {k2, 20}, {k3, 30}, {k4, 20.9}, {k6, "Hello world"}]
L2 = [{k1, 90}, {k2, 210}, {k3, 60}, {k4, 66.9}, {k6, "Hello universe"}]
L3 = [...]
现在我想要一个结果组合列表:
FinalList = [
{k1, [10, 90, ...]}, % '...' denotes values from other lists
{k2, [20, 210, ...]},
{K3, [30, 60, ...]},
{k4, [20.9, 66.9, ...]},
{K6, ["Hello world", "Hello universe", ...]}
]
我可以使用我的Old Posts Solutions:Combine/Merge Two Erlang lists进行合并但是我不确定如何将 L (列表列表)传递给该合并函数。
提前谢谢!
答案 0 :(得分:3)
您可以使用lists:foldl
将merge
应用于列表列表。这是一个例子:
-module(test).
-export([test/0]).
merge(L1, L2) ->
merge_(lists:sort(L1), lists:sort(L2)).
merge_([{K, V1}|T1], [{K, V2}|T2]) when is_list(V1), is_list(V2)
-> [{K, V1 ++ V2}|merge_(T1, T2)];
merge_([{K, V1}|T1], [{K, V2}|T2]) when is_list(V1)
-> [{K, V1 ++ [V2]}|merge_(T1, T2)];
merge_([{K, V1}|T1], [{K, V2}|T2]) when is_list(V2)
-> [{K, [V1] ++ V2}|merge_(T1, T2)];
merge_([{K, V1}|T1], [{K, V2}|T2])
-> [{K, [V1, V2]}|merge_(T1, T2)];
merge_([{K1, V1}|T1], [{K2, _}|_]=L2) when K1 < K2
-> [{K1, [V1]}|merge_(T1, L2)];
merge_(L1, [{K2, V2}|T2]) when is_list(V2)
-> [{K2, V2}|merge_(L1, T2)];
merge_(L1, [{K2, V2}|T2])
-> [{K2, [V2]}|merge_(L1, T2)];
merge_(L1, []) -> [{K, V} || {K, V} <- L1].
test() ->
L1 = [{k1, 10}, {k2, 20}, {k3, 30}, {k4, 20.9}, {k6, "Hello world"}],
L2 = [{k1, 90}, {k2, 210}, {k3, 60}, {k4, 66.9}, {k6, "Hello universe"}],
L3 = [{k1, 45}, {k2, 35}, {k3, 37}, {k4, 77.9}, {k6, "Hello cosmo"}],
lists:foldl(fun merge/2, [], [L1, L2, L3]).
结果如下:
36> test:test().
[{k1,"-Z\n"},
{k2,[35,210,20]},
{k3,[37,60,30]},
{k4,[77.9,66.9,20.9]},
{k6,"Hello cosmoHello universeHello world"}]
如您所见,
您需要修改merge
函数来处理列表(不仅仅是原始问题中的原子)。它已在我的示例代码中完成,该代码基于Vychodil's answer。
您需要修改merge
函数以正确处理字符串(如键k1和k6中的证据)。你应该能够自己解决它。
最后但并非最不重要的是,你应该在解决问题时接受答案。检查this link了解原因。
答案 1 :(得分:3)
我得到了启发,并得到了这个功能,假设所有列表都有相同的键(这似乎是这里的情况):
merge_lists([First|_]=ListOfLists) ->
Keys = proplists:get_keys(First),
lists:map(fun(Key) ->
{key,lists:flatmap(fun(List) ->
[proplists:get_value(Key,List)]
end
,ListOfLists)}
end
,Keys).
请原谅格式化:此函数首先获取它应该查找的键,然后按键编译每个列表中的值列表(不需要以这种方式更新累加器)。可能是一个单行,但这将是一个很长的路线;)
一些测试列表的结果(L3 = L1,但没有键k6
,这就是未定义的原因):
1> test:merge_lists([L1,L3,L2]).
[{k1,"\n\nZ"},
{k2,[20,20,210]},
{k3,[30,30,60]},
{k4,[20.9,20.9,66.9]},
{k6,["Hello world",undefined,"Hello universe"]}]
编辑:这可能是一种更容易理解的格式。看起来也更好:
merge_lists([First|_]=ListOfLists) ->
MapKeys = fun(Key) ->
MapLists = fun(List) -> [proplists:get_value(Key,List)] end,
Values = lists:flatmap(MapLists ,ListOfLists),
{Key,Values} end,
lists:map(MapKeys,proplists:get_keys(First)).
答案 2 :(得分:2)
Berzemus对相关问题的回答很容易适应:
merge(ListOfLists) ->
Combined = lists:append(ListOfLists),
Fun = fun(Key) -> {Key,proplists:get_all_values(Key,Combined)} end,
lists:map(Fun,proplists:get_keys(Combined)).
但是,如果L
中有许多列表或者它们很长,那么效率会非常低。在这种情况下,您应该从Vychodil的解决方案开始。