![](/img/trans.png)
[英]Elixir/Erlang: Error when a variable list merge with many other lists
[英]Merge inner lists of a list erlang
我有一個清單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解決方案進行合並 : 合並/合並兩個Erlang列表但是我不確定如何將L (列表列表)傳遞給該合並函數。
先感謝您!
您可以使用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的答案 。
您需要修改merge
函數以正確處理字符串(如鍵k1和k6中的證據)。 你應該能夠自己解決它。
最后但同樣重要的是,您應該在解決問題時接受答案。 檢查此鏈接了解原因。
我得到了啟發,並得到了這個功能,假設所有列表都有相同的鍵(這似乎是這里的情況):
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)).
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的解決方案開始。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.