2017-01-23 6 views
2

Ich habe eine Liste von 4 Elementen und es sieht aus wie:Python2 Liste der Listen von Wert fusionieren

L = [['grape','green',2, 100], ['grape','purple',3,3], ['apple','red',2, 15], ['apple','greed',3, 10], 
    ['apple','red',4, 4], ['banana','yellow',2, 3]] 

I diese Liste durch das erste Element, um eine Funktion haben, möchte zu fusionieren, verketten die zweite und die dritte Element, dann das letzte Element zusammenzufassen, wie die Ausgabe zu erhalten:

[['grape',['green,purple'],[2,3],103],['banana','yellow',2, 3],['apple',['red','green','red'],[2,3,4],29] 

ich die Folge Code versucht:

[(x,sum(map(itemgetter(3),y))) for x,y in itertools.groupby(L, itemgetter(0))], which can successfully sum up the last element, but 

[(x,(map(itemgetter(1),y)),(map(itemgetter(2),y)),sum(map(itemgetter(3),y))) for x,y in itertools.groupby(L, itemgetter(0))] 

hat nicht so funktioniert, wie ich es erwartet hatte.

Gibt es eine Möglichkeit, dies zu tun?

+0

Wenn es in der Gruppe nur ein Element ist sollte das zweite und dritte Element im Ergebnis sein Listen? – niemmi

+0

Entweder list oder unlist (Elemente) wird in Ordnung sein –

Antwort

4

Mit itertools.groupby() Sie zwei separate Iteration benötigen:

In [20]: [[i[0], j, k, sum(z)] for i, j, k, z in [zip(*g) for _, g in groupby(L, itemgetter(0))]] 
Out[20]: 
[['grape', ('green', 'purple'), (2, 3), 103], 
['apple', ('red', 'greed', 'red'), (2, 3, 4), 29], 
['banana', ('yellow',), (2,), 3]] 

Hier ist eine andere Art und Weise collections.defaultdict verwenden, aber nicht, dass optimize:

In [34]: d = defaultdict(list) 

In [35]: for i, j, k, z in L: 
      d[i].append((j, k, z)) 
    ....:  

In [36]: [[i, j, k, sum(z)] for i, j, k, z in [[i, *zip(*values)] for i, values in d.items()]] 
Out[36]: 
[['banana', ('yellow',), (2,), 3], 
['apple', ('red', 'greed', 'red'), (2, 3, 4), 29], 
['grape', ('green', 'purple'), (2, 3), 103]] 

Hinweis dass *zip(...) innerhalb einer Liste in- genannt wird packen Entpacken und ist nur in Python 3.5+ verfügbar.

+0

Beachten Sie, dass das Ergebnis hier ist "['Banana', ('gelb',), (2,), 3]' anstelle von '['Banane', 'gelb', 2, 3] 'wie in der Frage. – niemmi

+0

@niemmi Ja, aber lassen wir das als eine Aufgabe für OP;) – Kasramvd

1

Eine andere Lösung basiert auf groupby, ein bisschen weniger verstrickt und geben genau die gewünschte Leistung:

import operator, itertools 

l = [['grape','green',2, 100], ['grape','purple',3,3], ['apple','red',2, 15], ['apple','greed',3, 10], 
    ['apple','red',4, 4], ['banana','yellow',2, 3]] 


res = [] 
for key, group in itertools.groupby(l, operator.itemgetter(0)): 
    i,j,k,l = [i[0] if len(i) == 1 else list(i) for i in zip(*group)] 
    res.append([key, j, k, l if type(l) == int else sum(l)]) 

print(res) 

Ausgang:

[['grape', ['green', 'purple'], [2, 3], 103], ['apple', ['red', 'greed', 'red'], [2, 3, 4], 29], ['banana', 'yellow', 2, 3]] 
+0

Danke! Ein sicherer Weg, es zu tun! –