erlang:按元素位置拆分或过滤列表

时间:2014-11-25 15:13:49

标签: list erlang

Erlang中根据元素位置将给定列表拆分为子列表的最正确(也是最快)方法是什么?例如。我想得到列表中每个第N个元素的子列表:[1,2,3,14,5,16,7,8]到[1,14,7],[2,5,8],[3, 16]? N可以有任何合理的价值。

2 个答案:

答案 0 :(得分:1)

没有功能可以过滤列表中的位置,因此您必须使用split:

1> Sp = fun Sp(L,N,R) when length(L) =< N -> lists:reverse([L|R]);          
1> Sp(L,N,R) -> {L1,L2} = lists:split(N,L), Sp(L2,N,[L1|R]) end.            
#Fun<erl_eval.42.90072148>
2> Split= fun (L,N) when is_list(L), is_integer(N), N > 0 -> Sp(L,N,[]) end.
#Fun<erl_eval.12.90072148>
3> Split([1,2,3,4,5,6,7,8],3).                                              
[[1,2,3],[4,5,6],[7,8]]
4>

[edit] 哎呀,它没有回答这个问题。如果您不介意子列表的顺序,可能还有其他解决方案

1> L = [1,2,3,4,5,6,7,8].
[1,2,3,4,5,6,7,8]
2> N = 3.
3
3> [lists:reverse(Y) || Y <- lists:foldl(fun(X,[H|T]) -> T++[[X|H]] end , lists:duplicate(N,[]),L)].               
[[3,6],[1,4,7],[2,5,8]]
4> 

下一个版本恢复订单:

1> F = fun(List,Chunk) -> {Si,L1} = lists:foldl(fun(X,{S,[H|T]}) -> {S+1,T++[[X|H]]} end , {0,lists:duplicate(Chunk,[])},List),
1> {L2,L3} = lists:split(Chunk - Si rem Chunk,L1),                              
1> [lists:reverse(Y) || Y <- L3 ++ L2] end.                                     
#Fun<erl_eval.12.90072148>
2> F(lists:seq(1,130),11).    
[[1,12,23,34,45,56,67,78,89,100,111,122],
 [2,13,24,35,46,57,68,79,90,101,112,123],
 [3,14,25,36,47,58,69,80,91,102,113,124],
 [4,15,26,37,48,59,70,81,92,103,114,125],
 [5,16,27,38,49,60,71,82,93,104,115,126],
 [6,17,28,39,50,61,72,83,94,105,116,127],
 [7,18,29,40,51,62,73,84,95,106,117,128],
 [8,19,30,41,52,63,74,85,96,107,118,129],
 [9,20,31,42,53,64,75,86,97,108,119,130],
 [10,21,32,43,54,65,76,87,98,109,120],
 [11,22,33,44,55,66,77,88,99,110,121]]
3>

答案 1 :(得分:1)

你真的需要最快的方式吗?每次我以最简单(最天真)的方式开始实施。只有当我意识到它是性能瓶颈时,我才会开始优化它。

所以,最天真的方式:

split(List, ByElem) ->
  do_split(List, lists:duplicate(ByElem, []), []).

do_split([], RestGroups, Acc) ->
  Groups = lists:reverse(Acc) ++ RestGroups,
  [ lists:reverse(G) || G <- Groups ];

do_split([Elem | Rest], [Group | RestGroups], Acc) ->
  do_split(Rest, RestGroups, [[Elem | Group] | Acc]);

do_split(List, [], Acc) ->
  do_split(List, lists:reverse(Acc), []).

实际上,我认为与此代码的性能无关,我也没有看到任何方法来显着改进它。