合并/合并两个Erlang列表
如何在erlang中组合元组列表?我有以下清单:合并/合并两个Erlang列表,erlang,Erlang,如何在erlang中组合元组列表?我有以下清单: L1 = [{k1, 10}, {k2, 20}, {k3, 30}, {k4, 20.9}, {k6, "Hello world"}], 及 现在我想要一个组合列表,如下所示: L3 = [ {k1, [10, 90]}, {k2, [20, 210]}, {K3, [30, 60]}, {k4, [20.9, 66.9]}, {K6, ["Hello world", "H
L1 = [{k1, 10}, {k2, 20}, {k3, 30}, {k4, 20.9}, {k6, "Hello world"}],
及
现在我想要一个组合列表,如下所示:
L3 = [
{k1, [10, 90]},
{k2, [20, 210]},
{K3, [30, 60]},
{k4, [20.9, 66.9]},
{K6, ["Hello world", "Hello universe"]}
].
也许这不是最好的方法,但它能实现你想要实现的目标
merge([{A, X}| T1], [{A, Y} | T2], Acc) ->
New_acc = [{A, [X, Y]} | Acc],
merge(T1, T2, New_acc);
merge([{A, X} | T1], [{B, Y} | T2], Acc) ->
New_acc = [{A, [X]}, {B, Y} | Acc],
merge(T1, T2, New_acc);
merge([], [{B, Y} | T], Acc) ->
New_acc = [{B, Y} | Acc],
merge([], T, New_acc);
merge([{A, X} | T], [], Acc) ->
New_acc = [{A, X} | Acc],
merge(T, [], New_acc);
merge([], [], Acc) ->
lists:reverse(Acc).
编辑
我假设输入列表的顺序与示例输入相同。如果没有,您可以在合并之前使用
列表:sort/2
对它们进行排序。更短的东西,列表甚至不必拥有相同的键,并且可以无序排列:
merge(In1,In2) ->
Combined = In1 ++ In2,
Fun = fun(Key) -> {Key,proplists:get_all_values(Key,Combined)} end,
lists:map(Fun,proplists:get_keys(Combined)).
乐趣可以直接写在list:map/2
函数中,但这使它可读
输出,带有示例中的数据:
1> test:merge(L1,L2).
[{k1,"\nZ"},
{k2,[20,210]},
{k3,[30,60]},
{k4,[20.9,66.9]},
{k6,["Hello world","Hello universe"]}]
“\nZ”
是因为erlang将[10,90]解释为字符串(实际上是列表)。不用麻烦了。这种技术称为合并连接。它在数据库设计中是众所周知的
merge(L1, L2) ->
merge_(lists:sort(L1), lists:sort(L2)).
merge_([{K, V1}|T1], [{K, V2}|T2]) -> [{K, [V1, V2]}|merge_(T1, T2)];
merge_([], []) -> [].
如果两个列表中可能有不同的键集,并且您愿意删除这些值,则可以使用这些值
merge_([{K, V1}|T1], [{K, V2}|T2]) -> [{K, [V1, V2]}|merge_(T1, T2)];
merge_([{K1, _}|T1], [{K2, _}|_]=L2) when K1 < K2 -> merge_(T1, L2);
merge_(L1, [{_, _}|T2]) -> merge_(L1, T2);`
merge_(_, []) -> [].
或
列表:zipwith/2发生了什么事
假设:
- 列表长度相同
- 列表以相同的顺序包含相同的键
列表:zipwith(fun({X,Y},{X,Z})->{X,[Y,Z]}end,L1,L2)。
使用Erlang标准库中的sofs
模块可以很好地解决这个问题。sofs
模块描述了一种用于处理数学集合的DSL。这是其中的一种情况,您可以通过将数据转换到SOFS世界中来利用它,在该世界中对其进行操作,然后再将其转换回外部
请注意,我确实稍微更改了L3,因为sofs
不保留字符串顺序
-module(z).
-compile(export_all). % Don't do this normally :)
x() ->
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, [10, 90]},{k2, [20, 210]},{k3, [30, 60]},{k4, [20.9, 66.9]},{k6, ["Hello universe", "Hello world"]}],
R = sofs:relation(L1 ++ L2),
F = sofs:relation_to_family(R),
L3 = sofs:to_external(F),
ok.
谢谢,我试试这个建议!我得到了结果,但不确定为什么在第一个元组中得到\nZ:10>a:combine\u list()。[{k1,“\nZ”},{k2,[20210]},{k3,[30,60]},{k4,[20.9,66.9]},{k6,[“你好世界”,“你好宇宙”]}.
Pl.帮助。谢谢,我假设输入列表的顺序与示例输入相同@卡洛斯:哦,那么很抱歉,它们没有定购。好吧,你可以使用列表:keysort/2
。谢谢@carlo和Berzemus的建议这似乎很有趣!谢谢在这里,字符串顺序没有那么重要。太棒了!感谢这真是太好了,我从来没有想到过使用高级集合运算,也许是因为我非常喜欢数学;)非常酷和漂亮,在一行。谢谢
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]) -> [{K2, [V2]}|merge_(L1, T2)];
merge_(L1, []) -> [{K, [V]} || {K, V} <- L1].
merge(L1, L2) ->
merge(lists:sort(L1), lists:sort(L2), []).
merge([{K, V1}|T1], [{K, V2}|T2], Acc) -> merge(T1, T2, [{K, [V1, V2]}|Acc]);
merge([], [], Acc) -> Acc. % or lists:reverse(Acc).
merge([{K, V1}|T1], [{K, V2}|T2], Acc) -> merge(T1, T2, [{K, [V1, V2]}|Acc]);
merge([{K1, _}|T1], [{K2, _}|_]=L2, Acc) when K1 < K2 -> merge(T1, L2, Acc);
merge(L1, [{_, _}|T2], Acc) -> merge(L1, T2, Acc);`
merge(_, [], Acc) -> Acc. % or lists:reverse(Acc).
merge([{K, V1}|T1], [{K, V2}|T2], Acc) -> merge(T1, T2, [{K, [V1, V2]}|Acc]);
merge([{K1, V1}|T1], [{K2, _}|_]=L2, Acc) when K1 < K2 -> merge(T1, L2, [{K1, [V1]}|Acc]);
merge(L1, [{K2, V2}|T2], Acc) -> merge(L1, T2, [{K2, [V2]}|Acc]);`
merge([{K1, V1}|T1], [], Acc) -> merge(T1, [], [{K1, [V1]} | Acc]);
merge([], [], Acc) -> Acc. % or lists:reverse(Acc).
% or merge(L1, [], Acc) -> lists:reverse(Acc, [{K, [V]} || {K, V} <- L1]).
% instead of two last clauses.
merge(L1, L2) ->
merge(lists:sort(L1), lists:sort(L2), []).
merge([{K1, _}|_]=L1, {K2, _}|_]=L2, Acc) ->
K = min(K1, K2),
{Vs1, T1} = collect(K, L1, []),
{Vs2, T2} = collect(K, L2, Vs1),
merge(T1, T2, [{K, Vs2}|Acc]);
merge([{K, _}|_]=L1, [], Acc) ->
{Vs, T1} = collect(K, L1, []),
merge(T1, [], [{K, Vs}|Acc]);
merge([], [{K, _}|_]=L2, Acc) ->
{Vs, T2} = collect(K, L2, []),
merge([], T2, [{K, Vs}|Acc]);
merge([], [], Acc) -> lists:reverse(Acc).
collect(K, [{K, V}|T], Acc) -> collect(K, T, [V|Acc]);
collect(_, T, Acc) -> {Acc, T}.
-module(z).
-compile(export_all). % Don't do this normally :)
x() ->
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, [10, 90]},{k2, [20, 210]},{k3, [30, 60]},{k4, [20.9, 66.9]},{k6, ["Hello universe", "Hello world"]}],
R = sofs:relation(L1 ++ L2),
F = sofs:relation_to_family(R),
L3 = sofs:to_external(F),
ok.