10
votes

Fractionnement d'une liste dans des morceaux de taille égale à Erlang

Je veux scinder: xxx pré>

dans: p> xxx pré>

Ça fonctionne généralement bien avec: p>

[ lists:sublist(List, X, 2) || X <- lists:seq(1,length(List),2) ] .


1 commentaires

Remarque juste: Votre solution avec la compréhension de la liste fonctionne si lente car listes: subliste / 3 La complexité d'exécution est O (n), la complexité globale des algorithmes est donc O (n ^ 2)


8 Réponses :


0
votes

Vous pouvez le faire comme ceci:

1> {List1, List2} = lists:partition(fun(X) -> (X rem 2) == 1 end, List).
{[1,3,5|...],[2,4,6|...]}
2> lists:zipwith(fun(X, Y) -> [X, Y] end, List1, List2).
[[1,2],[3,4],[5,6]|...]


0 commentaires

8
votes

Voici deux solutions rapides pour vous qui sont à la fois flexibles. L'un est facile à lire, mais seulement un peu plus vite que votre solution proposée. L'autre est assez rapide, mais est un cryptique à lire bits. Et notez que mes deux algorithmes proposés fonctionnera pour les listes de quoi que ce soit, non seulement des listes numériques commandés.

Voici le « facile à lire » un. Appelez par n_length_chunks (Liste, chunkSize) code>. Par exemple, pour obtenir une liste des morceaux 2 long, appel n_length_chunks (Liste, 2) code>. Cela fonctionne pour des morceaux de toute taille, à savoir, vous pouvez appeler n_length_chunks (Liste, 4) code> pour obtenir [[1,2,3,4], [5,6,7,8 ] ...] code> p>

n_length_chunks_fast(List,Len) ->
  LeaderLength = case length(List) rem Len of
      0 -> 0;
      N -> Len - N
  end,
  Leader = lists:duplicate(LeaderLength,undefined),
  n_length_chunks_fast(Leader ++ lists:reverse(List),[],0,Len).

n_length_chunks_fast([],Acc,_,_) -> Acc;
n_length_chunks_fast([H|T],Acc,Pos,Max) when Pos==Max ->
    n_length_chunks_fast(T,[[H] | Acc],1,Max);
n_length_chunks_fast([H|T],[HAcc | TAcc],Pos,Max) ->
    n_length_chunks_fast(T,[[H | HAcc] | TAcc],Pos+1,Max);
n_length_chunks_fast([H|T],[],Pos,Max) ->
    n_length_chunks_fast(T,[[H]],Pos+1,Max).


3 commentaires

JA, je sais que et pourquoi c'est lent. Je voulais juste savoir si une belle compréhension de la liste pourrait être écrite faire le travail. Mais toujours merci. Maintenant, je sais au moins que j'ai compris les bases d'Erlang.


Je changerais n_length_chunks (liste, len) lorsque LEN> Longueur (Liste) -> Liste; à n_length_chunks (liste, len) lorsque Len> Longueur (liste) -> [Liste]; .


Bonne prise. Merci, corrigé!



19
votes

Essayez ceci: XXX PRE>

Test dans Erlang-Shell (j'ai déclaré cette fonction dans le module partie code>): p>

2> part:part([1,2,3,4,5,6,7,8]).
[[1,2],[3,4],[5,6],[7,8]]
3> 
3> timer:tc(part, part, [lists:seq(1,10000)]).
{774,
 [[1,2],
  [3,4],
  [5,6],
  [7,8],
  "\t\n","\v\f",
  [13,14],
  [15,16],
  [17,18],
  [19,20],
  [21,22],
  [23,24],
  [25,26],
  [27,28],
  [29,30],
  [31,32],
  "!\"","#$","%&","'(",")*","+,","-.","/0","12","34",
  [...]|...]}


3 commentaires

Solution la plus rapide dans mes tests.


Il a fallu 40 mois, mais, Mate, enfin, vous avez mérité ces 10 points! ;)


Merci, @marcus! :-)



3
votes

ou avec un pli: xxx


1 commentaires

Je ne l'ai pas encore testé, mais cela ressemble à un excellent exemple pour replier à mon avis! (Peut-être que ce devrait être fait, mais ce qui est possible ...) Je ne savais pas que cela est possible du tout. Merci beaucoup.



1
votes

Je tiens à soumettre une solution légèrement compliquée mais plus flexible (et la plupart plus rapide) de celle proposée par @tilman xxx

la partie fonction peut être implémentée comme xxx

MISE À JOUR J'ai ajouté d'inverse au cas où vous voulez conserver la commande, mais comme je peux le constater, il n'ajoute pas plus de 20% du temps de traitement.


0 commentaires

0
votes

Voici une réponse plus générale qui fonctionne avec n'importe quelle taille subliste.

-module(n_length_chunks_fast).

-export([n_length_chunks_fast/2]).

n_length_chunks_fast(List,Len) ->
    SkipLength = case length(List) rem Len of
        0 -> 0;
        N -> Len - N
    end,
    n_length_chunks_fast(lists:reverse(List),[],SkipLength,Len).

n_length_chunks_fast([],Acc,_Pos,_Max) -> Acc;

n_length_chunks_fast([H|T],Acc,Pos,Max) when Pos==Max ->
    n_length_chunks_fast(T,[[H] | Acc],1,Max);

n_length_chunks_fast([H|T],[HAcc | TAcc],Pos,Max) ->
    n_length_chunks_fast(T,[[H | HAcc] | TAcc],Pos+1,Max);

n_length_chunks_fast([H|T],[],Pos,Max) ->
    n_length_chunks_fast(T,[[H]],Pos+1,Max).


0 commentaires

-1
votes

J'ai légèrement modifié la mise en œuvre de @jlarky pour supprimer l'expression de garde, qui devrait être légèrement plus rapide:

split_list(List, Max) ->
    element(1, lists:foldl(fun
        (E, {[Buff|Acc], 1}) ->
            {[[E],Buff|Acc], Max};
        (E, {[Buff|Acc], C}) ->
            {[[E|Buff]|Acc], C-1};
        (E, {[], _}) ->
            {[[E]], Max}
    end, {[], Max}, List)).


0 commentaires

0
votes

Je cherchais une fonction de partition pouvant diviser une grande liste à une petite quantité de travailleurs. Avec la partition de Lkuty Vous pourriez obtenir qu'un travailleur devient presque double travail que tous les autres. Si ce n'est pas ce que vous voulez, voici une version que les longueurs sublistes diffèrent au plus 1.

utilise approprié < / a> pour tester. xxx

tests: xxx


0 commentaires