如何根据原始列表对列表进行排序?

时间:2016-12-02 14:06:38

标签: erlang

如何基于另一个列表对列表进行排序,例如:

  

列表= [1,2,3,4,5]。

我有一个函数发送此列表和一个函数,以便将列表元素应用于worker,例如:

  

发件人(List,F)

     

worker()将应用F(列表元素)

并将发送方函数逐个发送回元素。 这里,发送元素的结果可能与发送者发送的顺序不同。 所以,如果我发送[1,2,3,4,5],工人可能会以这种方式发回列表

  

[结果(2),结果(5),结果(1),结果(4),结果(3)]

我的问题是:如何根据原始列表对结果列表进行排序

1 个答案:

答案 0 :(得分:1)

<强> tldr;这里简短的回答是,如果您想保留排序,工作人员需要知道他们正在处理的元素的索引并将其返回给调用者,以便可以重新组合列表

我建议将项目的索引发送给每个工作人员(例如F(Element, Index))。然后,不仅仅发送结果,而是发送结果和索引({Index, Result}),因此当您从每个工作人员获得结果时,您知道它在列表中的位置。然后使用选择性接收将它们按顺序放回:

results_from_workers(Max) ->
  results_from_workers(Max, 0, []).

results_from_workers(Max, Num, NewList) when Num > Max ->
  % If the next number is greater than the max, reverse the list and return it
  lists:reverse(NewList);
results_from_workers(Max, Num, NewList) ->
  % Receive the result for the next number
  receive
    {Num, Result} ->
      results_from_workers(Num + 1, [Result|NewList])
  end.

% Then call your code that starts the workers
sender(List,F),

% Then call `results_from_workers/1` with the length of the list being processed, it should return the new list
NewList = results_from_workers(length(List)).

这样做的缺点是,如果进程崩溃,results_from_workers进程将挂起等待崩溃进程的结果。您应该将工作进程链接到启动它们的进程,因此这不应成为问题。如果由于某种原因您不能或不想链接到工作进程,可以在接收中使用after Timeout -> failed子句,Timeout是表示超时的整数(以毫秒为单位)。请注意,如果您的工作时间超过预期,则可能会执行timeout子句,但不会产生结果。