2016-12-10 2 views
-1

Ich habe eine verschachtelte Liste wie folgt aussehen:Summe verschachtelt basierte Listen unter der Bedingung in Python

[['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78], 
['London','2014',4800,70,90],['Bern','2013',300,450,678], 
['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]] 

Was ich tun möchte, ist mit einem anderen sublist jeden Integer in der Unterliste Summieren wenn Stadt und Jahr gleich sind. Ich dachte zuerst an ein Wörterbuch mit Stadt und Jahr als Schlüssel, aber es verursachte Probleme, es zu sortieren.

Dann hatte ich: {('Vienna','2012'):[890,503,70],('Bern','2013'):[800,1150,768],...}

ich so etwas wie dies auch versucht:

[sum(x) for x in zip(*list) if x[0] == x[0]] aber natürlich ist es nicht funktioniert hat.

Kann ich so etwas mit einer verschachtelten Liste machen, damit die Sortierung nach Stadt und Jahr einfacher ist?

Antwort

2

Sie könnten ein Ergebnis erstellen dict wo Schlüssel ist Tupel der ersten beiden Elemente in den ursprünglichen Listen und Wert ist list von Zahlen. Jedes Mal, wenn Sie den Wert dict hinzufügen, können Sie get verwenden, um entweder ein vorhandenes Element oder einen vorgegebenen Standardwert zurückzugeben, in diesem Fall eine leere Liste.

Sobald Sie die vorhandene Liste und Liste hinzufügen können Sie zip_longest mit fillvalue verwenden, um Zahlen aus beiden Listen zu summieren. zip_longest gibt Tupel der Länge 2 zurück, die aus jeder Liste eine Zahl enthalten. Wenn eine Liste länger als andere ist, wird fillvalue als Standard verwendet, so dass dies auch funktioniert, wenn Listen unterschiedlich lang sind. Liste Schließlich Verständnis verwendet wird, könnte jedes Element für einen neuen Wert zu summieren:

from itertools import zip_longest 

l = [ 
    ['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78], 
    ['London','2014',4800,70,90],['Bern','2013',300,450,678], 
    ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90] 
] 

res = {} 
for x in l: 
    key = tuple(x[:2]) 
    res[key] = [i + j for i, j in zip_longest(res.get(key, []), x[2:], fillvalue=0)] 

print(res) 

Ausgang:

{('Vienna', '2013'): [700, 850, 90], ('London', '2014'): [10200, 949, 168], 
('Vienna', '2012'): [890, 503, 70], ('Bern', '2013'): [800, 1150, 768]} 

Wenn Sie die Städte alphabetisch und Jahre neuste zuerst könnte passieren Sie benutzerdefinierte key-sorted sortieren möchten:

for item in sorted(res.items(), key=lambda x: (x[0][0], -int(x[0][1]))): 
    print(item) 

Ausgang:

(('Bern', '2013'), [800, 1150, 768]) 
(('London', '2014'), [10200, 949, 168]) 
(('Vienna', '2013'), [700, 850, 90]) 
(('Vienna', '2012'), [890, 503, 70]) 
+0

Das sieht sehr gut aus. Verwenden Sie 'res = collections.OrderedDict()', um zu verbessern. – Gribouillis

+0

Auch mit 'defaultdict (list)' kannst du 'res [key]' anstelle von 'res.get (key, []) schreiben' – Poloq

+0

Vielen Dank, die Sortierung war hauptsächlich der Teil, den ich nicht mit a verwaltet habe dict! Danke vielmals! – IamnotaRabbit

0

Sie sollten ein Wörterbuch verwalten, wie Sie in der Frage beschrieben haben. So etwas wie dies helfen wird,

cities = {} 
for a in list: 
    city_key = a[:1] 
    if city_key in cities: 
     cities[city_key] = [a + b for a, b in zip(a[2:], cities[city_key])] 
    else: 
     cities[city_tuple] = a[2:] 
+0

Ok, ich habe es schon fast so gemacht wie du. Das Problem ist, dass ich die Ausgabe sortieren muss. Es sollte wie folgt aussehen: Wien 2014 .... 2013 .... was wäre der einfachste Weg, dies zu tun? – IamnotaRabbit

+0

Sie können die Schlüssel leicht sortieren http://stackoverflow.com/questions/9001509/how-can-i-sort-a-dictionary-by-key – martianwars

0

Eine Möglichkeit ist die Liste der Listen in einem dict der Schlüssel Sie möchten (die Stadt und Jahr) zu spalten.Auch die defaultdict hilft Quetschen alle Entfernungen in eine flache Liste

>>> from collections import defaultdict 
>>> dct = defaultdict(list) 
>>> for item in lst: 
... dct[(item[0], item[1])].extend(item[2:]) 

Jetzt dct die ganzen Zahlen hat durch die Stadt und Jahr gruppiert:

>>> dct 
defaultdict(<type 'list'>, {('Vienna', '2013'): [700, 850, 90], ('London', '2014'): [5400, 879, 78, 4800, 70, 90], ('Vienna', '2012'): [890, 503, 70], ('Bern', '2013'): [300, 450, 678, 500, 700, 90]}) 

Und Sie können sie einfach zusammenfassen:

>>> for key in dct: 
... print(key, sum(dct[key])) 
... 
(('Vienna', '2013'), 1640) 
(('London', '2014'), 11317) 
(('Vienna', '2012'), 1463) 
(('Bern', '2013'), 2718) 
0
nl = [['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78], 
     ['London','2014',4800,70,90],['Bern','2013',300,450,678], 
     ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]] 
d = {} 
for l in nl: 
    key = l[0] , l[1] 
    value = l[2:] 
    if key not in d: 
     d[key] = value 
    else: 
     d[key] = [sum(i)for i in zip(d[key], value)] 
print(d) 

aus:

{('Vienna', '2012'): [890, 503, 70], ('London', '2014'): [10200, 949, 168], ('Bern', '2013'): [800, 1150, 768], ('Vienna', '2013'): [700, 850, 90]} 
0

Die Lösung mit itertools.groupby und operator.itemgetter Funktionen:

import itertools, operator 

l = [['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78], 
['London','2014',4800,70,90],['Bern','2013',300,450,678], 
['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]] 

getter = operator.itemgetter(0, 1) # the sequence to be grouped(first two items) 
summed = [[k[0],k[1],sum(sum(d[2:]) for d in list(group))] 
      for k, group in itertools.groupby(sorted(l, key=getter), getter)] 

print(summed) 

Der Ausgang:

[['Bern', '2013', 2718], ['London', '2014', 11317], ['Vienna', '2012', 1463], ['Vienna', '2013', 1640]] 
Verwandte Themen