Summe der Werte in der Liste, wenn die Bedingung erfüllt ist

stimmen
1

Ich habe eine Python - Liste lInstanzen der Klasse enthält Element:

class Element:
    def __init__(self, id, value):
        self.id = id
        self.value = value

l = [Element(1, 100), Element(1, 200), Element(2, 1), Element(3, 4), Element(3, 4)]

Jetzt möchte ich alle summieren valueMitglieder der Klassen , Elementswenn sie idgleich ist , diese Liste zu erhalten:

l = [Element(1, 300), Element(2, 1), Element(3, 8)]

Was ist der pythonic Weg, dies zu tun?

Veröffentlicht am 19/12/2018 um 14:11
quelle vom benutzer
In anderen Sprachen...                            


3 antworten

stimmen
6

Es gibt (fast?) Nichts , was itertoolsnicht tun. Schauen Sie sich auf groupby:

from itertools import groupby
from operator import attrgetter


class Element:
    def __init__(self, id, value):
        self.id = id
        self.value = value
    def __repr__(self):  # kudos @mesejo
        return "Element({}, {})".format(self.id, self.value)

l = [Element(1, 100), Element(1, 200), Element(2, 1), Element(3, 4), Element(3, 4)]

l.sort(key=attrgetter('id'))  # if it is already sorted by 'id', comment-out

res = [Element(g, sum(sub.value for sub in k)) for g, k in groupby(l, key=attrgetter('id'))]

was in ... resultiert:

print(res)   # [Element(1, 300), Element(2, 1), Element(3, 8)]
Beantwortet am 19/12/2018 um 14:17
quelle vom benutzer

stimmen
2

Eine Möglichkeit wäre, eine zu schaffen , defaultdictdie IDs zu Summen von Werten abbildet. Dann können wir diese Ergebnisse nehmen und nutzen sie , um eine neue Liste von zu bauen Elements. Eine Möglichkeit , das zu tun , ist zu verwenden , um starmapdie Elemente dieses Wörterbuch kartieren auf die Argumente zuElement

from collections import defaultdict
from itertools import starmap

class Element:
    def __init__(self, id, value):
        self.id = id
        self.value = value
    def __repr__(self):
        return "Element({}, {})".format(self.id, self.value)

l = [Element(1, 100), Element(1, 200), Element(2, 1), Element(3, 4), Element(3, 4)]

d = defaultdict(int)

for e in l:
    d[e.id] += e.value

print(list(starmap(Element, d.items())))
# [Element(1, 300), Element(2, 1), Element(3, 8)]
Beantwortet am 19/12/2018 um 14:18
quelle vom benutzer

stimmen
1

Sie können auch das gewünschte Ergebnis mit setnur die eindeutigen IDs zu erhalten und sumdie Werte insgesamt. Zum Beispiel:

class Element:
    def __init__(self, id, value):
        self.id = id
        self.value = value

l = [Element(1, 100), Element(1, 200), Element(2, 1), Element(3, 4), Element(3, 4)]

ids = set(elem.id for elem in l)
totals = [Element(i, sum(elem.value for elem in l if elem.id == i)) for i in ids]
# [Element(1, 300), Element(2, 1), Element(3, 8)]
Beantwortet am 19/12/2018 um 14:36
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more