2012-04-12 4 views
-1

Ich bin auf der Suche nach einer schönen Möglichkeit, einen Generator zu schreiben, der einen Strom von Elementen aus einer anderen Liste/Generator/iterable nimmt und gruppiert sie.Pythonic Muster für eine Gruppierung Generator

Teilen ist einfach. Zum Beispiel, wenn wir Zeilen einer Datei zu übernehmen wollen und sie in Zeichen aufgeteilt:

def lines2chars(filename): 

    with open(filename) as fh: 

     for line in fh:     # Iterate over items 
      for char in line:   # Split items up 
       yield char    # Yield smaller items 

sie Gruppierung, die Absätze zum Beispiel zu produzieren, scheint schwierig. Das ist, was ich mir ausgedacht habe:

def lines2para(filename): 

    with fh as open(filename): 
     paragraph = []     # Start with an empty group 

     while True:      # Infinite loop to be ended by exception 
      try: 
       line = next(fh)   # Get a line 
      except StopIteration as e: 
             # If there isn't one... 
             # do whatever necessary 
       raise     # and raise StopIteration for the caller 
      else: 
       paragraph.append(line) # Add to the group of items 
       if line == "\n":  # If we've got a whole group 
        yield paragraph  # yield it 
        paragraph = []  # and start a new group 

Es ist nicht meiner Meinung nach hübsch. Es benutzt die Interna des Iterationsprotokolls, hat eine Endlosschleife, die ausbricht, und liest mir einfach nicht gut. Hat jemand eine schönere Art, diese Art von Code zu schreiben?

Denken Sie daran, ich suche nach dem Muster, anstatt dieses spezifische Beispiel. In meinem Fall lese ich Daten, die über Pakete verteilt sind, die über Pakete verteilt sind, aber jede Ebene ist etwas ähnlich dem Absatz Beispiel.

+2

Was ist los mit http://docs.python.org/library/itertools.html#itertools.groupby? – luke14free

+0

Sind die Antworten auf diese Frage hilfreich? http://StackOverflow.com/q/3862010/311220 – Acorn

+0

@ luke14free Hmmm, funktioniert definitiv für den Absatz Beispiel, aber Sie haben mir klar gemacht, dass ich für meine paketierte Datenstrom eine laufende Zählung der Daten haben muss in jedem Paket. Mein Beispiel war nicht gut genug. Ich werde meine Frage ein wenig aktualisieren, aber ich muss zur Arbeit, sonst bin ich noch später als ich schon bin. –

Antwort

1
import itertools as it 

def lines2para(filename): 
    with open(filename) as fh: 
     for k, v in it.groupby(fh, key=lambda x: bool(x.strip())): 
      if k: 
       yield list(v) 
+0

Sie haben meine Frage beantwortet, aber ich habe festgestellt, dass meine Frage nicht genau das ist, was ich brauche. Ich werde ein wenig nachbearbeiten –