x = [(5, 65),
 (2, 12),
 (5, 18),
 (3, 35),
 (4, 49),
 (4, 10),
 (1, 27),
 (1, 1),
 (4, 71),
 (2, 41),
 (2, 17),
 (1, 25),
 (2, 62),
 (5, 65),
 (4, 5),
 (1, 51),
 (1, 13),
 (5, 92),
 (2, 62),
 (5, 81)]

У меня есть список вложенных кортежей, и я хочу суммировать второе значение по первому. Поскольку в настоящее время в первом столбце 5 значений, я бы получил 5 возвращенных значений, которые были бы суммой второго значения в каждой записи, где совпало первое значение.

Я ищу что-то вроде [117, 194, 35, 135, 321]. Это заказано 1, 2, 3, 4, 5, но мне, честно говоря, даже не нужно, чтобы это было по порядку, мне просто нужен список сумм.

Я пытаюсь достичь этого, используя понимание списков в Python, так как я узнал об этом, и я борюсь с этим примером.

0
Bo Anderson 11 Окт 2021 в 19:56

4 ответа

Лучший ответ

Если вам нужно их отсортировать, используйте itertools.groupby:

from itertools import groupby
from operator import itemgetter

x = [(5, 65), (2, 12), (5, 18), (3, 35), (4, 49), (4, 10), (1, 27), (1, 1), (4, 71), (2, 41),
     (2, 17), (1, 25), (2, 62), (5, 65), (4, 5), (1, 51), (1, 13), (5, 92), (2, 62), (5, 81)]


result = [sum(v for _, v in value) for key, value in groupby(sorted(x), key=itemgetter(0))]
print(result)

Вывод

[117, 194, 35, 135, 321]

Но приведенный выше подход не очень эффективен, поэтому я предлагаю вам использовать defaultdict:

from collections import defaultdict

x = [(5, 65), (2, 12), (5, 18), (3, 35), (4, 49), (4, 10), (1, 27), (1, 1), (4, 71), (2, 41),
     (2, 17), (1, 25), (2, 62), (5, 65), (4, 5), (1, 51), (1, 13), (5, 92), (2, 62), (5, 81)]


counts = defaultdict(int)
for key, value in x:
    counts[key] += value

result = [v for _, v in sorted(counts.items())]
print(result)

Вывод

[117, 194, 35, 135, 321]

Как показывает практика, когда вы имеете дело со значениями, которые необходимо уменьшить или накапливать с помощью ключа, использование списка может быть не самым эффективным подходом.

Примечание

Самый эффективный подход, который подходит вашему примеру и только вашему примеру (небольшое количество ключей в небольшом диапазоне [1, 5]), - это просто сделать:

result = [0 for _ in range(5)]
for key, value in x:
    result[key - 1] += value

print(result)
1
Dani Mesejo 11 Окт 2021 в 17:12

Используй словарь:

d = dict()
for i, val in x:
   d.setdefault(i , 0)
   d[i] += val
result = list(d.items())
1
qouify 11 Окт 2021 в 17:00

Использование pandas:

>>> import pandas as pd
>>> df = pd.DataFrame(x)
>>> df.groupby(0).sum()[1].tolist()
[117, 194, 35, 135, 321]

Используя itertools.groupby:

>>> from itertools import groupby
>>> keys, values = map(iter, zip(*sorted(x)))
>>> [sum(g) for _, g in groupby(values, lambda _: next(keys))]
[117, 194, 35, 135, 321]
1
Jab 11 Окт 2021 в 17:16

Простое решение, использующее только понимание списка:

x = [(5, 65),
     (2, 12),
     (5, 18),
     (3, 35),
     (4, 49),
     (4, 10),
     (1, 27),
     (1, 1),
     (4, 71),
     (2, 41),
     (2, 17),
     (1, 25),
     (2, 62),
     (5, 65),
     (4, 5),
     (1, 51),
     (1, 13),
     (5, 92),
     (2, 62),
     (5, 81)]


key_range = set([k for k, _ in x])
res = [sum([v for k, v in x if k == i]) for i in key_range]
0
Davide Madrisan 11 Окт 2021 в 17:15