2013-03-22 5 views
5

Ich habe das Gefühl, Python sollte eine eingebaute haben, um dies zu tun. Nehmen Sie eine Liste von Elementen und wandeln Sie sie in ein Wörterbuch um, indem Sie Schlüssel zu einer Liste von Elementen mit diesem gemeinsamen Schlüssel zuordnen.Gruppieren von Elementen mit einem Schlüssel?

Es ist einfach genug zu tun:

# using defaultdict 
lookup = collections.defaultdict(list) 
for item in items: 
    lookup[key(item)].append(item) 

# or, using plain dict 
lookup = {} 
for item in items: 
    lookup.setdefault(key(item), []).append(item) 

Aber das ist häufig genug von einem Anwendungsfall, die eine eingebaute Funktion wäre schön. Ich kann es selbst implementieren, wie zum Beispiel:

def grouped(iterable, key): 
    result = {} 
    for item in iterable: 
     result.setdefault(key(item), []).append(item) 
    return result 

lookup = grouped(items, key) 

Dieser anders als itertools.groupby in einigen wichtigen Punkten. Um das gleiche Ergebnis von groupby zu bekommen, dann würden Sie haben, dies zu tun, das ist ein wenig hässlich ist:

lookup = dict((k, list(v)) for k, v in groupby(sorted(items, key=key), key)) 

Einige Beispiele:

>>> items = range(10) 
>>> grouped(items, lambda x: x % 2) 
{0: [0, 2, 4, 6, 8], 1: [1, 3, 5, 7, 9]} 

>>> items = 'hello stack overflow how are you'.split() 
>>> grouped(items, len) 
{8: ['overflow'], 3: ['how', 'are', 'you'], 5: ['hello', 'stack']} 

Gibt es einen besseren Weg?

+1

Ich sehe nicht, wie dies ein "häufig genug von einem Anwendungsfall" ist. Ich benutze es selten und wenn es sein muss, ist die Verwendung eines 'defaultdict' einfach perfekt. AFAIK gibt es keine eingebauten, die tun, was Sie selbst wollen. – Bakuriu

+0

Sie haben wahrscheinlich Recht, aber ein Teil von mir denkt, dass dies genauso gut von einem eingebauten wie groupby ist. – FogleBird

Antwort

3

Ich habe diese Frage auch an comp.lang.python gestellt, und der Konsens scheint zu sein, dass dies nicht wirklich genug ist, um eine eingebaute Funktion zu rechtfertigen. Also, die offensichtlichen Ansätze sind am besten. Sie arbeiten und sie sind lesbar.

# using defaultdict 
lookup = collections.defaultdict(list) 
for item in items: 
    lookup[key(item)].append(item) 

# or, using plain dict 
lookup = {} 
for item in items: 
    lookup.setdefault(key(item), []).append(item) 

Ich wollte meine Frage löschen, aber ich könnte dies auch hier lassen, falls über ihn jemand stolpert nach Informationen zu suchen.

+1

Siehe meine Antwort unten für, wie Sie eine Funktion extrahieren können, um dasselbe wie oben zu tun, aber ungefähr die gleiche API wie 'groupby' verwendend. – tobych

1

Wenn Sie etwas mit etwa der gleichen API wie groupby wollten, könnten Sie verwenden:

def groupby2(iterable, keyfunc): 
    lookup = collections.defaultdict(list) 
    for item in iterable: 
     lookup[keyfunc(item)].append(item) 
    return lookup.iteritems() 

das ist also das gleiche wie Ihr Beispiel oben, aber in eine Funktion machte die iteritems der Verweistabelle Rückkehr Sie‘ ve gebaut.

Verwandte Themen