2013-03-22 14 views
5

Mam wrażenie, że Python powinien mieć wbudowany, aby to zrobić. Zrób listę przedmiotów i zamień je na słownik odwzorowujący klawisze do listy elementów z tym kluczem.Grupowanie elementów według klucza?

To dość łatwe do zrobienia:

# 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) 

Ale to wystarczająco często z przypadku użycia że wbudowana funkcja byłoby miło. Mogłem mu realizować się jako takie:

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

lookup = grouped(items, key) 

To jest inna niż itertools.groupby w kilku ważnych dziedzinach. Aby uzyskać ten sam wynik z groupby, trzeba by to zrobić, co jest trochę brzydki:

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

Kilka przykładów:

>>> 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']} 

jest jakiś lepszy sposób?

+1

Nie widzę, jak to jest "częsty przypadek użycia". Używam go rzadko i kiedy muszę, użycie 'defaultdict' jest po prostu idealne. AFAIK nie ma żadnego wbudowanego, który robi to, co chcesz sam. – Bakuriu

+0

Prawdopodobnie masz rację, ale część mnie uważa, że ​​jest tak samo ważna jak wbudowany jako groupby. – FogleBird

Odpowiedz

3

Też zaksięgowałem to pytanie do comp.lang.python, i konsensus wydaje się, że to nie jest faktycznie pospolity dość by uzasadnić wbudowaną funkcję. Tak więc, stosując oczywiste podejścia, najlepiej. Działają i są czytelne.

# 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) 

miałem zamiar usunąć moje pytanie, ale równie dobrze mogę zostawić to tutaj na wypadek gdyby ktoś potyka się po nim szuka informacji.

+1

Zobacz moją odpowiedź poniżej, w jaki sposób można wyodrębnić funkcję, aby zrobić to samo, jak powyżej, ale przy użyciu w przybliżeniu tego samego interfejsu API co 'groupby'. – tobych

1

Jeśli chciałeś coś z grubsza tego samego API jako groupby, można użyć:

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

Więc to jest takie samo jak powyższy przykład, ale wykonane w zwracanej przez funkcję iteritems tabeli przeglądowej you” ve zbudowany.

Powiązane problemy