Aufteilung einer Liste in N Teile von ungefähr gleicher Länge

Was ist der beste Weg, um eine Liste in ungefähr gleiche Teile aufzuteilen? Zum Beispiel, wenn die Liste hat 7 Elemente und ist es in 2 Teile aufgeteilt, wollen wir 3 Elemente in einem Teil zu bekommen, und das andere sollte 4 Elemente haben.

Ich suche etwas wie even_split(L, n) , das L in n Teile bricht.

 def chunks(L, n): """ Yield successive n-sized chunks from L. """ for i in xrange(0, len(L), n): yield L[i:i+n] 

Der Code oben gibt Chunks von 3, anstatt 3 Chunks. Ich könnte einfach transponieren (Iteration über diese und nehmen Sie das erste Element jeder Spalte, rufen Sie diesen Teil eins, dann nehmen Sie die zweite und legte es in Teil zwei, etc.), aber das zerstört die Bestellung der Elemente.

17 Solutions collect form web for “Aufteilung einer Liste in N Teile von ungefähr gleicher Länge”

Hier ist eine, die funktionieren könnte:

 def chunkIt(seq, num): avg = len(seq) / float(num) out = [] last = 0.0 while last < len(seq): out.append(seq[int(last):int(last + avg)]) last += avg return out 

Testen:

 >>> chunkIt(range(10), 3) [[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]] >>> chunkIt(range(11), 3) [[0, 1, 2], [3, 4, 5, 6], [7, 8, 9, 10]] >>> chunkIt(range(12), 3) [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]] 

Solange du nichts dummes wie ständige Stücke willst:

 >>> def chunkify(lst,n): ... return [ lst[i::n] for i in xrange(n) ] ... >>> chunkify( range(13), 3) [[0, 3, 6, 9, 12], [1, 4, 7, 10], [2, 5, 8, 11]] 

Sie können es ganz einfach als Listengenerator schreiben:

 def split(a, n): k, m = divmod(len(a), n) return (a[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in xrange(n)) 

Beispiel:

 >>> list(split(range(11), 3)) [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10]] 

Ändern des Codes, um n Brocken zu liefern, anstatt Stücke von n :

 def chunks(l, n): """ Yield n successive chunks from l. """ newn = int(len(l) / n) for i in xrange(0, n-1): yield l[i*newn:i*newn+newn] yield l[n*newn-newn:] l = range(56) three_chunks = chunks (l, 3) print three_chunks.next() print three_chunks.next() print three_chunks.next() 

Was gibt:

 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35] [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55] 

Dies wird die zusätzlichen Elemente der endgültigen Gruppe zuordnen, die nicht perfekt ist, aber gut in deiner Spezifikation von "grob N gleichen Teilen" 🙂 Damit meine ich 56 Elemente wäre besser als (19,19,18), während dies gibt (18,18,20).

Sie können die ausgewogenere Ausgabe mit dem folgenden Code erhalten:

 #!/usr/bin/python def chunks(l, n): """ Yield n successive chunks from l. """ newn = int(1.0 * len(l) / n + 0.5) for i in xrange(0, n-1): yield l[i*newn:i*newn+newn] yield l[n*newn-newn:] l = range(56) three_chunks = chunks (l, 3) print three_chunks.next() print three_chunks.next() print three_chunks.next() 

Welche Ausgänge:

 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37] [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55] 

Dies ist die raison d'être für numpy.array_split *:

 >>> L [0, 1, 2, 3, 4, 5, 6, 7] >>> print(*np.array_split(L, 3)) [0 1 2] [3 4 5] [6 7] 

* Kredit zu zero piraeus im zimmer 6

Hier ist eine, die None hinzufügt, um die Listen gleich zu machen

 >>> from itertools import izip_longest >>> def chunks(l, n): """ Yield n successive chunks from l. Pads extra spaces with None """ return list(zip(*izip_longest(*[iter(l)]*n))) >>> l=range(54) >>> chunks(l,3) [(0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51), (1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52), (2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53)] >>> chunks(l,4) [(0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52), (1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53), (2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, None), (3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, None)] >>> chunks(l,5) [(0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50), (1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51), (2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52), (3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53), (4, 9, 14, 19, 24, 29, 34, 39, 44, 49, None)] 

Werfen Sie einen Blick auf numpy.split :

 >>> a = numpy.array([1,2,3,4]) >>> numpy.split(a, 2) [array([1, 2]), array([3, 4])] 

Implementierung mit numpy.linspace-Methode.

Geben Sie einfach die Anzahl der Teile an, in die das Array eingeteilt werden soll. Die Divisionen werden von nahezu gleicher Größe sein.

Beispiel:

 import numpy as np a=np.arange(10) print "Input array:",a parts=3 i=np.linspace(np.min(a),np.max(a)+1,parts+1) i=np.array(i,dtype='uint16') # Indices should be floats split_arr=[] for ind in range(i.size-1): split_arr.append(a[i[ind]:i[ind+1]] print "Array split in to %d parts : "%(parts),split_arr 

Gibt:

 Input array: [0 1 2 3 4 5 6 7 8 9] Array split in to 3 parts : [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8, 9])] 

Hier ist meine Lösung:

 def chunks(l, amount): if amount < 1: raise ValueError('amount must be positive integer') chunk_len = len(l) // amount leap_parts = len(l) % amount remainder = amount // 2 # make it symmetrical i = 0 while i < len(l): remainder += leap_parts end_index = i + chunk_len if remainder >= amount: remainder -= amount end_index += 1 yield l[i:end_index] i = end_index 

Produziert

  >>> list(chunks([1, 2, 3, 4, 5, 6, 7], 3)) [[1, 2], [3, 4, 5], [6, 7]] 

Hier ist ein Generator, der jede positive (ganzzahlige) Anzahl von Chunks behandeln kann. Wenn die Anzahl der Chunks größer ist als die Eingangslistenlänge, werden einige Chunks leer sein. Dieser Algorithmus wechselt zwischen kurzen und langen Chunks, anstatt sie zu trennen.

Ich habe auch einige Code zum Testen der Funktion ragged_chunks .

 ''' Split a list into "ragged" chunks The size of each chunk is either the floor or ceiling of len(seq) / chunks chunks can be > len(seq), in which case there will be empty chunks Written by PM 2Ring 2017.03.30 ''' def ragged_chunks(seq, chunks): size = len(seq) start = 0 for i in range(1, chunks + 1): stop = i * size // chunks yield seq[start:stop] start = stop # test def test_ragged_chunks(maxsize): for size in range(0, maxsize): seq = list(range(size)) for chunks in range(1, size + 1): minwidth = size // chunks #ceiling division maxwidth = -(-size // chunks) a = list(ragged_chunks(seq, chunks)) sizes = [len(u) for u in a] deltas = all(minwidth <= u <= maxwidth for u in sizes) assert all((sum(a, []) == seq, sum(sizes) == size, deltas)) return True if test_ragged_chunks(100): print('ok') 

Wir können dies etwas effizienter machen, indem wir die Multiplikation in den range exportieren, aber ich denke, die vorherige Version ist besser lesbar (und DRYer).

 def ragged_chunks(seq, chunks): size = len(seq) start = 0 for i in range(size, size * chunks + 1, size): stop = i // chunks yield seq[start:stop] start = stop 

Hier ist eine weitere Variante, die die "verbleibenden" Elemente gleichmäßig unter allen Klumpen verbreitet, eine zu einer Zeit, bis es noch keine gibt. Bei dieser Implementierung treten die größeren Stücke am Anfang des Prozesses auf.

 def chunks(l, k): """ Yield k successive chunks from l.""" if k < 1: yield [] raise StopIteration n = len(l) avg = n/k remainders = n % k start, end = 0, avg while start < n: if remainders > 0: end = end + 1 remainders = remainders - 1 yield l[start:end] start, end = end, end+avg 

Zum Beispiel erzeugen 4 Chunks aus einer Liste von 14 Elementen:

 >>> list(chunks(range(14), 4)) [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10], [11, 12, 13]] >>> map(len, list(chunks(range(14), 4))) [4, 4, 3, 3] 

Das gleiche wie die Antwort des Jobs , aber berücksichtigt Listen mit der Größe kleiner als die Anzahl der Chuncks.

 def chunkify(lst,n): [ lst[i::n] for i in xrange(n if n < len(lst) else len(lst)) ] 

Wenn n (Anzahl der Chunks) 7 ist und lst (die Liste zu teilen) ist [1, 2, 3] die Chunks sind [[0], [1], [2]] anstelle von [[0], [1 ], [2], [], [], [], []]

Wenn du n Elemente in grob k Chunks teilt, kannst du n % k Chunks 1 Element größer machen als die anderen Chunks, um die zusätzlichen Elemente zu verteilen.

Der folgende Code gibt Ihnen die Länge für die Chunks:

 [(n // k) + (1 if i < (n % k) else 0) for i in range(k)] 

Beispiel: n=11, k=3 ergibt [4, 4, 3]

Sie können dann leicht berechnen, die Start-Indizes für die Chunks:

 [i * (n // k) + min(i, n % k) for i in range(k)] 

Beispiel: n=11, k=3 ergibt [0, 4, 8]

Mit dem i+1 te chunk als die grenze bekommst du, dass das i te Stück der Liste l mit len n ist

 l[i * (n // k) + min(i, n % k):(i+1) * (n // k) + min(i+1, n % k)] 

Als letzter Schritt erstellen Sie eine Liste aus allen Chunks mit List-Verständnis:

 [l[i * (n // k) + min(i, n % k):(i+1) * (n // k) + min(i+1, n % k)] for i in range(k)] 

Beispiel: n=11, k=3, l=range(n) ergibt [range(0, 4), range(4, 8), range(8, 11)]

Du könntest auch:

 split=lambda x,n: x if not x else [x[:n]]+[split([] if not -(len(x)-n) else x[-(len(x)-n):],n)][0] split([1,2,3,4,5,6,7,8,9],2) [[1, 2], [3, 4], [5, 6], [7, 8], [9]] 

Ein anderer Weg wäre so etwas wie hier, die Idee hier ist, Grupper zu benutzen, aber loszuwerden, None . In diesem Fall werden wir alle "small_parts" aus Elementen im ersten Teil der Liste und "big_parts" aus dem späteren Teil der Liste gebildet. Länge der 'größeren Teile' ist len ​​(small_parts) + 1. Wir müssen x als zwei verschiedene Unterteile betrachten.

 from itertools import izip_longest import numpy as np def grouper(n, iterable, fillvalue=None): # This is grouper from itertools "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" args = [iter(iterable)] * n return izip_longest(fillvalue=fillvalue, *args) def another_chunk(x,num): extra_ele = len(x)%num #gives number of parts that will have an extra element small_part = int(np.floor(len(x)/num)) #gives number of elements in a small part new_x = list(grouper(small_part,x[:small_part*(num-extra_ele)])) new_x.extend(list(grouper(small_part+1,x[small_part*(num-extra_ele):]))) return new_x 

Wie ich es eingerichtet habe, gibt eine Liste von Tupeln zurück:

 >>> x = range(14) >>> another_chunk(x,3) [(0, 1, 2, 3), (4, 5, 6, 7, 8), (9, 10, 11, 12, 13)] >>> another_chunk(x,4) [(0, 1, 2), (3, 4, 5), (6, 7, 8, 9), (10, 11, 12, 13)] >>> another_chunk(x,5) [(0, 1), (2, 3, 4), (5, 6, 7), (8, 9, 10), (11, 12, 13)] >>> 

Um das linspace zu runden und es als Index zu verwenden, ist eine einfachere Lösung als das, was amit12690 vorschlägt.

 function chunks=chunkit(array,num) index = round(linspace(0,size(array,2),num+1)); chunks = cell(1,num); for x = 1:num chunks{x} = array(:,index(x)+1:index(x+1)); end end 

Mit Listenverständnis:

 def divide_list_to_chunks(list_, n): return [list_[start::n] for start in range(n)] 
  • Python verschmilzt zwei Listen mit allen möglichen Permutationen
  • Python - Liste der Listen in Spalten auflisten
  • Ersetzen Sie Sonderzeichen in einer String-Python
  • Subset-Liste basierend auf dem Wert des Wörterbuch-Elements
  • Schreiben Sie eine CSV ohne Trennzeichen in Python
  • Split nur Teil der Liste in Python
  • Wie konvertiert man eine String-Liste in eine Ganzzahl in python [duplicate]
  • Wie spalte ich eine csv-Datei in gleichmäßig sortierte Chunks in Python?
  • Python: Ein Dict aus einer Liste, die auf etwas im Dict basiert
  • Konvertieren von Strings in Floats in einer verschachtelten Liste
  • In-Place Wörterbuch-Inversion in Python
  • Python ist die beste Programmiersprache der Welt.