2011-11-11 11 views
16

Ho una lista enorme di tuple in questo formato. Il secondo campo di ciascuna tupla è il campo categoria.Dividi un elenco di tuple in sotto-elenchi dello stesso campo di tuple

[(1, 'A', 'foo'), 
    (2, 'A', 'bar'), 
    (100, 'A', 'foo-bar'), 

    ('xx', 'B', 'foobar'), 
    ('yy', 'B', 'foo'), 

    (1000, 'C', 'py'), 
    (200, 'C', 'foo'), 
    ..] 

Qual è il modo più efficace per una scomposizione in sotto-liste della stessa categoria (A, B, C., Ecc)?

+0

possibile duplicato di [Ordinamento di sub-elenchi in nuovi sotto-elenchi?] (Http://stackoverflow.com/questions/71140 38/sorting-sub-lists-into-new-sub-lists) – agf

risposta

22

Uso itertools.groupby:

import itertools 
import operator 

data=[(1, 'A', 'foo'), 
    (2, 'A', 'bar'), 
    (100, 'A', 'foo-bar'), 

    ('xx', 'B', 'foobar'), 
    ('yy', 'B', 'foo'), 

    (1000, 'C', 'py'), 
    (200, 'C', 'foo'), 
    ] 

for key,group in itertools.groupby(data,operator.itemgetter(1)): 
    print(list(group)) 

cede

[(1, 'A', 'foo'), (2, 'A', 'bar'), (100, 'A', 'foo-bar')] 
[('xx', 'B', 'foobar'), ('yy', 'B', 'foo')] 
[(1000, 'C', 'py'), (200, 'C', 'foo')] 

Oppure, per creare una lista con ogni gruppo come un elenco secondario, è possibile utilizzare una lista di comprensione:

[list(group) for key,group in itertools.groupby(data,operator.itemgetter(1))] 

Il seco nd argomento a itertools.groupby è una funzione che si applica a itertools.groupby per ogni articolo in data (il primo argomento). Si prevede di restituire un key. itertools.groupby quindi raggruppa tutti gli elementi contigui con lo stesso key.

operator.itemgetter(1) preleva il secondo elemento in sequenza.

Per esempio, se

row=(1, 'A', 'foo') 

poi

operator.itemgetter(1)(row) 

uguale 'A'.


Come @eryksun sottolinea nei commenti, se le categorie di tuple appaiono in un certo ordine casuale, quindi è necessario ordinare data prima di applicare itertools.groupby. Questo perché itertools.groupy raccoglie solo articoli contigui con la stessa chiave in gruppi.

Per ordinare le tuple per categoria, utilizzare:

data2=sorted(data,key=operator.itemgetter(1)) 
+6

Non dimenticare che i dati devono prima essere ordinati: 'data2 = sorted (data, key = operator.itemgetter (1))'. – eryksun

+1

Grazie per una risposta molto definitiva. –

+0

Ottima risposta, non dimenticare che puoi usare una lambda al posto dell'operatore, per gente abituata a lambda. – jwg

1

Per ottenere risultati più elenchi di single da una lista di tuple:

foo = ((1,2), (3, 4), (5, 6), (7,8) , (9, 10)) 
[[z[i] for z in foo] for i in (0,1)] 

Se si preferisce ottenere più tuple di single:

zip(*[(1,4),(2,5),(3,6)]) 
Problemi correlati