【问题标题】:erlang: split or filter list by element positionerlang:按元素位置拆分或过滤列表
【发布时间】:2015-01-23 16:03:34
【问题描述】:

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

【问题讨论】:

    标签: list erlang


    【解决方案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), []).
    

    实际上,我认为这段代码的性能与性能无关,而且我看不到任何显着改进它的方法。

    【讨论】:

      【解决方案2】:

      没有过滤列表中位置的功能,所以你必须使用拆分:

      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>
      

      【讨论】:

      • 我知道如何简单地拆分列表,但在这里我需要创建一个包含第 N 个元素的列表。 IE。每 3 个元素列表: 3> Split([1,2,3,4,5,6,7,8],3)。 [[1,4,7],[2,5,8],[3,6]]
      • @Darkkey,我放了一个版本来回答你最初的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-06
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多