对列表中的所有元素求和,而不重复已计算的元素

时间:2016-03-24 21:07:29

标签: recursion erlang list-comprehension

我正在尝试使用另一种语言(例如Java或JavaScript)中的双重for循环来获得结果。

所以我能想出的最接近的是:

1> L = [1,2,3].
[1,2,3]
2> R = [X + Y || X <- L, Y <- L].
[2,3,4,3,4,5,4,5,6]
3> 

...但我真正想要的是:[3,4,5]。我不想总结已添加的元素:

A1 + A2
A2 + A3
A2 + A1 [already computed, position switched]
A2 + A3 [already computed, position switched]
A3 + A1
A3 + A2 [already computed, position switched]

提前致谢...

1 个答案:

答案 0 :(得分:2)

<强> TL; DR

[X+Y || X <- L, Y <- L, Y > X].

其他解决方案

您基本上希望两个迭代器沿着相同的数据结构和累加器一起运行,以收集独特元素的总和。没有理由你无法在Erlang中模仿这样的迭代器:

-module(sum2).
-export([start/1]).

start(Max) ->
    L = lists:seq(1, Max),
    T = list_to_tuple(L),
    do_sum(T, 1, 2, size(T), []).

do_sum(T, X, S, S, A) when X + 1 =:= S ->
    lists:reverse([mk_sum(X, S, T) | A]);
do_sum(T, X, S, S, A) ->
    do_sum(T, X + 1, X + 2, S, [mk_sum(X, S, T) | A]);
do_sum(T, X, Y, S, A) ->
    do_sum(T, X, Y + 1, S, [mk_sum(X, Y, T) | A]).

mk_sum(X, Y, T) -> element(X, T) + element(Y, T).

结果:

7> c(sum2).
{ok,sum2}
8> sum2:start(3).
[3,4,5]
9> sum2:start(5).
[3,4,5,6,5,6,7,7,8,9]

如果您没有要汇总的元素列表但只有整数,实际上有一个更简单的解决方案:

-module(sum3).
-export([start/1]).

start(Max) -> do_sum(1, 2, Max, []).

do_sum(X, S, S, A) when X + 1 =:= S -> lists:reverse([X + S | A]);
do_sum(X, S, S, A) -> do_sum(X + 1, X + 2, S, [X + S | A]);
do_sum(X, Y, S, A) -> do_sum(X, Y + 1, S, [X + Y | A]).

甚至是一个只有列表理解的简单解决方案:

4> L = [1, 2, 3].
[1,2,3]
5> [X+Y || X <- L, Y <- L, Y > X].
[3,4,5]
6> f().
ok
7> L = [1,2,3,4,5].
[1,2,3,4,5]
8> [X+Y || X <- L, Y <- L, Y > X].
[3,4,5,6,5,6,7,7,8,9]

另请查看此问题Erlang; list comprehension without duplicates,该问题可解决类似问题并对可能的解决方案有更多想法。