2015-05-12 13 views
10

Mam płaską listę unikatowych obiektów, z których niektóre mogą współdzielić dany atrybut z innymi. Chcę utworzyć zagnieżdżoną listę list z obiektami pogrupowanymi według podanego atrybutu. Jako minimalną przykład podano następującą listę:Zagnieżdżanie płaskiej listy na podstawie dowolnego kryterium

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

może chcę go przez grupę długości, np

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

Widziałem parę similarquestions i suggestions. Jednak we wszystkich tych przypadkach zagnieżdżanie opiera się na uporządkowaniu listy wejściowej. W moim przypadku uporządkowanie listy wejściowej jest całkowicie nieprzewidywalne, podobnie jak liczba podlist dla wyjścia i liczba pozycji na podlistę.

Czy istnieje standardowa funkcja lub idiomatyczny sposób osiągnięcia tego?

Odpowiedz

10

Wspólne idiom do istniejącej listy jest użycie groupby w itertools:

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 

Albo, bardziej zwięźle:

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

Wydruki:

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

Wejście do groupby jest pogrupowane w grupy na podstawie zmiany wartości wyjściowej funkcji klucza, w w tym przypadku len. Zasadniczo należy wstępnie uporządkować listę na podstawie tej samej funkcji klucza, aby funkcja sorted została wywołana jako pierwsza.

Jeśli lista źródłowa nie została jeszcze zakończona, czy nie Sortable na podstawie kryteriów (czy też po prostu wolą inną opcję), należy utworzyć dict, który mapuje kryteria unikalnej wartości klucza:

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

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

można również użyć defaultdict zamiast setDefault z arbitralnej wartości klucza:

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

w obu przypadkach, to można utworzyć listę z zagnieżdżonego że:

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

Doceniam twoją dokładność. Podejrzewałem, że nie będzie takiej funkcji jak groupby, ale sztuczka ze słownika jest po prostu sprytna. Dzięki! – Joe

Powiązane problemy