Flache Liste strukturieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DaftWullie
User
Beiträge: 37
Registriert: Donnerstag 17. Mai 2012, 21:28

Hallo,

ich habe das Problem, aus einer flachen Liste wieder etwas strukturiertes zu machen, um das dann weiterzuverarbeiten. Konkret sind Gruppen von Daten durch eine oder mehrere "leere" Elemente getrennt. Ich möchte deshalb eine Funktion schreiben, die aus der flachen Liste eine Liste von Listen mit den "Nutzdaten" macht. Ich habe das auch umgesetzt, aber mir kommt meine Lösung so umständlich vor, da muss es doch bessere Möglichkeiten geben. Ich hatte es zunächst mit itertools.takewhile() versucht (also abwechselnd durch die leeren und die nichtleeren Elemente zu iterieren) dabei aber immer den letzten nichtleeren Datensatz "verloren".

Hier meine unschöne Funktion:

Code: Alles auswählen

import itertools as it

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = it.tee(iterable)
    next(b, None)
    return it.izip(a, b)

def unflat(entries):
    groups = []
    group_entries = []
    for entry, next_entry in pairwise(entries):
        if entry:
            group_entries.append(entry)
            if not next_entry:
                groups.append(group_entries)
                group_entries = []
##    print groups
    return groups

def main():
     print unflat([ '','abc' '', '', 'efgh', '', 'a', 'b', 'c', '', 'i', ''])

if __name__ == '__main__':
    main()

Code: Alles auswählen

>>> 
[['abc'], ['efgh'], ['a', 'b', 'c'], ['i']]
P.S. Ich weiß, dass die Funktion nicht funktioniert, falls nicht am Ende der Liste ein leeres Element steht. Das umgehe ich, indem ich der Liste immer ein leeres Element hinzufüge, bevor ich die Funktion aufrufe.
BlackJack

Ein Job für `itertools.groupby()`:

Code: Alles auswählen

from itertools import groupby


def unflatten(items):
    for true, group in groupby(items, bool):
        if true:
            yield list(group)

def main():
    data = ['', 'abc', '', '', 'efgh', '', 'a', 'b', 'c', '', 'i']
    print list(unflatten(data))


if __name__ == '__main__':
    main()
BlackJack

Oder als LC:

Code: Alles auswählen

def unflatten(items):
    return [list(group) for true, group in groupby(items, bool) if true]
DaftWullie
User
Beiträge: 37
Registriert: Donnerstag 17. Mai 2012, 21:28

Genau das habe ich gesucht! Danke!

Auf groupby hatte ich auch schon ein Auge geworfen, bin aber nicht auf die Idee gekommen, dort als Funktion einfach ein bool mitzugeben...

Das könnte man doch mal als recipe in die Python-Doc aufnehmen :wink:
Antworten