Сумма значений в списке при выполнении условия - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть список Python l, содержащий экземпляры класса 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)]

Теперь я хочу суммировать всех value членов классов Elements, если их idравно получению этого списка:

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

Какой самый питонический способ сделать это?

Ответы [ 3 ]

0 голосов
/ 19 декабря 2018

Один из способов - создать defaultdict, который сопоставляет идентификаторы с суммами значений.Затем мы можем взять эти результаты и использовать их для создания нового списка Elements.Один из способов сделать это - использовать starmap, чтобы сопоставить элементы этого словаря с аргументами Element

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)]
0 голосов
/ 19 декабря 2018

Вы также можете получить желаемый результат, используя set для получения только уникальных идентификаторов и sum для суммирования значений.Например:

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)]
0 голосов
/ 19 декабря 2018

Нет (почти?) Ничего, что itertools не может сделать.Взгляните на 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'))]

, что приводит к:

print(res)   # [Element(1, 300), Element(2, 1), Element(3, 8)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...