2015-05-12 12 views
10

Ich habe eine flache Liste von eindeutigen Objekten, von denen einige ein bestimmtes Attribut mit anderen teilen können. Ich möchte eine verschachtelte Liste von Listen erstellen, deren Objekte nach dem angegebenen Attribut gruppiert sind. Als minimal Beispiel die folgende Liste gegeben:Verschachteln Sie eine flache Liste basierend auf einem beliebigen Kriterium

>>> flat = ["Shoes", "pants", "shirt", "tie", "jacket", "hat"] 

ich es zu einer Gruppe von Länge wollen könnte, zum Beispiel:

>>> nest_by_length(flat) 
[['tie', 'hat'], ['shoes', 'pants', 'shirt'], ['jacket']] 

ich ein paar similarquestions und suggestions gesehen habe. In all diesen Fällen basiert die Verschachtelung jedoch auf der Reihenfolge der Eingabeliste. In meinem Fall ist die Reihenfolge der Eingabeliste völlig unvorhersehbar, ebenso wie die Anzahl der Unterlisten für die Ausgabe und die Anzahl der Elemente pro Unterliste.

Gibt es eine Standardfunktion oder einen idiomatischen Weg, dies zu erreichen?

Antwort

10

Ein gemeinsames Idiom für eine bestehende Liste ist groupby in itertools zu verwenden:

from itertools import groupby 

flat = ["Shoes", "pants", "shirt", "tie", "jacket", "hat"] 

result=[] 
for k, g in groupby(sorted(flat, key=len), key=len): 
    result.append(list(g)) 

print result 

Oder mehr lapidar:

[list(g) for _,g in groupby(sorted(flat, key=len), key=len)] 

Drucke:

[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']] 

Eingang zu groupby ist gruppiert in Gruppen basierend auf dem sich ändernden Wert der Ausgabe der Schlüsselfunktion, in dieser Fall len. Im Allgemeinen müssen Sie die Liste auf der Grundlage derselben Schlüsselfunktion vorbestellen, sodass die Funktion sorted zuerst aufgerufen wird.

Wenn Ihre Quellenliste noch nicht abgeschlossen ist, oder nicht die Kriterien sortierbar basieren (oder Sie lieber nur eine andere Option), ein dict erstellen, die Ihre Kriterien auf einen eindeutigen Schlüsselwert abbildet:

groups={} 
for e in flat: 
    groups.setdefault(len(e), []).append(e) 

print groups  
# {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']} 

Sie können auch defaultdict verwenden, anstatt setdefault mit dem beliebigen Schlüsselwert:

from collections import defaultdict 
groups=defaultdict(list) 
for e in flat: 
    groups[len(e)].append(e) 
# groups=defaultdict(<type 'list'>, {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']}) 

In jedem Fall können Sie die verschachtelte Liste aus, dass erstellen:

>>> [groups[k] for k in sorted(groups.keys())] 
[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']] 
+0

Ich schätze Ihre Gründlichkeit. Ich vermutete, dass es eine Funktion wie Gruppe geben würde, die ich nicht kannte, aber der Wörterbuchtrick ist einfach clever. Vielen Dank! – Joe

Verwandte Themen