在Erlang中将列表中的元素成对组合

3

我正在尝试在Erlang中对排序集合中的项目执行进程,我使用eredis调用ZRANGE KEY 0 -1 WITHSCORES,但问题是它返回了类似于[<<"item1">>, <<"100">>, <<"item2">>, <<"200">>]这样的结果。如何高效地运行函数f以便进行以下调用:f(<<"item1">>, <<"100">>), f(<<"item2">>, <<"200">>)

2个回答

2
我用类似这样的方法解决了它。
f([X,Y|T]) -> [do_the_job(X,Y)|f(T)];
f([]) -> [].

然后调用:

f(List).

有更高效的方法吗?


1
你应该直接调用函数,而不是先将其配对。如果你真的想要配对,那么你可能会使用元组。另一个答案中的尾递归版本只会在没有人再使用的古老版本的Erlang上更快。 - Peer Stritzinger

0

一种优化的方法是使用尾递归。您可以将列表传递到do/1函数中,并生成一个空列表来存储应用f/2函数于给定列表的每两个头部项的结果,然后返回这些结果:

do(List) ->
   do(List, []).
do([X,Y | Tail], Acc) ->
   do(Tail, [f(X, Y) | Acc]);
do([], Acc) ->
   lists:reverse(Acc).

f(X, Y) ->
   {X, Y}.

来自Erlang文档的一条关于尾递归效率的注释:

在大多数情况下,递归函数每次递归使用的堆栈空间比尾递归分配在堆上的空间更多。随着使用的内存越来越多,垃圾回收器会更频繁地被调用,并且它需要遍历更多的堆栈。


请注意引用旁边的段落:在R12B及以后的版本中,有一种优化方法,在许多情况下可以减少在身体递归调用中使用的堆栈单词数。一个身体递归列表函数和一个在结尾调用lists:reverse/1的尾递归函数将使用相同数量的内存。lists:map/2,lists:filter/2,列表推导式和许多其他递归函数现在使用与它们的尾递归等效项相同的空间。 - Peer Stritzinger
所以基线:这已经不重要了。 - Peer Stritzinger
此外,您的代码返回了一个反转的列表,这可能不是您想要的。我会添加一个反转来避免混淆。 - Peer Stritzinger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接