简体   繁体   English

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

[英]erlang: split or filter list by element position

What is the most correct (and fastest) way in Erlang to split the given list into sublists depending on the element position? Erlang中根据元素位置将给定列表拆分为子列表的最正确(最快)方法是什么? Eg I want to get the sublist of every Nth elements from list: [1,2,3,14,5,16,7,8] to [1,14,7], [2,5,8], [3,16]? 例如,我想从列表中获取每N个元素的子列表:[1,2,3,14,5,16,7,8]到[1,14,7],[2,5,8],[3 ,16]? The N could have any reasonable value. N可以具有任何合理的值。

There is no function to filter on position in a list, so you have to use split: 没有功能可以过滤列表中的位置,因此您必须使用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] Ooops, it doesn't answer the question. [编辑]糟糕,它无法回答问题。 If you don't mind the order of sublist, another solution maybe 如果您不介意子列表的顺序,则可能有另一种解决方案

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> 

the next version restore the order: 下一个版本恢复顺序:

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>

Do you really need the fastest way? 您真的需要最快的方法吗? Every time I start implementation with easiest (most naive) way. 每次我以最简单(最幼稚)的方式开始实施。 And only when I realize that it is performance bottleneck, I start optimize it. 并且只有当我意识到这是性能瓶颈时,我才开始对其进行优化。

So, most naive way: 所以,最幼稚的方式:

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), []).

Actually, I believe there is nothing to do with performance of this code, and I don't see any ways to dramatically improve it. 实际上,我认为此代码的性能与无关,并且我也没有任何方法可以显着改善它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM