2016-12-26 2 views
-2

erhalte ich den Dreh des grouper() Rezept von itertools:Grouper Rezept aber zurückkehren letzte „Gruppe“, auch mit unterschiedlicher Länge

def grouper(iterable, n, fillvalue=None): 
    "Collect data into fixed-length chunks or blocks" 
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return zip_longest(*args, fillvalue=fillvalue) 

Diese Version füllt die letzte Gruppe mit einem bestimmten Wert. Wenn ich fillvalue entferne, gibt es die letzte Gruppe nicht zurück, wenn sie weniger als n Elemente enthält. Ich habe mehrere Situationen erlebt, in denen ich die letzte Gruppe haben möchte, egal ob sie die gleiche Größe wie alle anderen Gruppen hat oder nicht. Ich möchte auch keine Auffüllung hinzufügen. Wie gehe ich dabei vor?

Antwort

1

Normalerweise verwende ich islice:

from itertools import islice 

def grouper(iterable, n): 
    iterator = iter(iterable) 
    group = tuple(islice(iterator, n)) 
    while group: 
     yield group 
     group = tuple(islice(iterator, n)) 

Wenn Sie es vorziehen, die folgende ist nur eine geringfügige Änderung in der Logik, aber es funktioniert auf die gleiche:

def grouper(iterable, n): 
    iterator = iter(iterable) 
    while True: 
     group = tuple(islice(iterator, n)) 
     if not group: 
      return 
     yield group 

Es andere Varianten sind auch hier . Zum Beispiel, wenn Sie eine völlig faul Version:

from itertools import groupby 

def grouper(iterable, n): 
    iterator = enumerate(iterable) 
    for unused_group_number, idx_items in groupby(iterator, lambda t: t[0] // n): 
     yield (item for unused_idx, item in idx_items) 

Dies ist wahrscheinlich weniger performant als islice, da es so viel nicht wieder in Python nennen, aber es ist völlig faul (und sicher). z.B. Es liefert Iteratoren über Gruppen und behandelt den Fall, in dem der Aufrufer nicht jedes Element in einem Gruppeniterator konsumiert.

+0

Sie tatsächlich vergessen, um die Werte von 'Islice zu lesen()' - versuchen 'Liste (Grouper ('ABCDEFG', 3)) 'zum Beispiel .. –

+0

Was ist der Unterschied zwischen der Rückgabe des Iterators direkt von' islice() 'vs Wrapping es in einem Tupel oder einer Liste? –

+0

@eugeney Da 'grouper()' ein Generator ist, weiß ich, wie man es benutzt. Ich werde wahrscheinlich etwas mehr tun, in Anlehnung an 'for x in grouper ('ABCDEFG', 3):' –

1

Sie islice() in einer Schleife verwenden können, um die Elemente in Stücke zu lesen:

from itertools import islice 

def grouper(iterable, n): 
    it = iter(iterable) 
    group = tuple(islice(it, n)) 
    while group: 
     yield group 
     group = tuple(islice(it, n))  

print(list(grouper('ABCDEFG', 3))) # [('A', 'B', 'C'), ('D', 'E', 'F'), ('G',)] 
+0

Was ist der Unterschied zwischen der Rückgabe eines Tupels und der Rückgabe des Iterators direkt aus 'islice()'? –

+0

@ Code-Apprentice: Wenn 'islice()' aufgerufen wird, wird der ursprüngliche Iterator nicht weiterentwickelt. Es gibt nur einen neuen Iterator zurück. Das Weglassen von 'tuple()' würde im angegebenen Beispiel zu einer Endlosschleife führen. –

Verwandte Themen