Невозможно получить сумму в словаре - PullRequest
0 голосов
/ 07 апреля 2019

Я пытаюсь суммировать все значения в моем словаре для каждого ключа.Пока что я использую defaultdict, и это мой словарь: scores = {10: [[1000], [1000]], 25: [[500],[500],[500]], 40: [[600]], 60: [[700]]}

Я хочу, чтобы 10: 2000 20: 1500

Так вот мой код: finalScores = {k:sum(v) for k,v in scores.items()}

Но вместо этого я получаю эту ошибку: unsupported operand type(s) for +: 'int' and 'list'

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

У меня сильная головная боль из-за этого

Ответы [ 5 ]

2 голосов
/ 07 апреля 2019

Используйте itertools.chain, чтобы сгладить каждый список.

from itertools import chain
{k: sum(chain.from_iterable(v)) for k, v in scores.items()}

chain.from_iterable - это метод класса, который, учитывая что-то вроде [[a,b,c], [d,e,f]], создает итератор, который возвращает значения из каждого подсписка по очереди.

0 голосов
/ 07 апреля 2019

A numpy решение:

import numpy as np
{k: np.sum(l) for k,l in scores.items()}
0 голосов
/ 07 апреля 2019

Если вы хотите применить одну функцию к списку объектов, которые все будут реагировать на эту функцию, вы хотите вызвать map():

map(sum, [[1,2,3],[2,3,4]]) # => [5, 9] ... sort of*

Программисты Python обычно предпочитают понимание списка длятакого рода вещи:

[sum(list) for list in list_of_lists]

Это очень похоже на понимание речи, которое вы уже делаете, и может быть либо скомбинировано следующим образом:

{k: sum(l) for (k, ll) in scores.items() for l in ll}

, либо выделено в какую-то логикуи в других местах.

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

В качестве заключительного замечания, в общем, при работе со списками списков, может быть полезно взглянуть на почтенный модуль itertools в stdlib или другой более полный ответвление, такое как more-itertools , которое, как и следовало ожидать, обеспечивает flatten()* функция 1021 *!(Хотя, как указывает другой ответчик, вы можете использовать chain.from_iterable для достижения того же самого из коробки из itertools)

* предостережение с map() в том, что оно на самом деле возвращает mapобъект, который будет перебирать сопоставленные значения.

0 голосов
/ 07 апреля 2019

Свести список списков с помощью sum(v,[]) перед его суммированием:

scores = {10: [[1000], [1000]], 25: [[500],[500],[500]], 40: [[600]], 60: [[700]]}
finalScores = {k:sum(sum(v,[])) for k,v in scores.items()}
print(finalScores)

Выход:

{10: 2000, 25: 1500, 40: 600, 60: 700}
0 голосов
/ 07 апреля 2019

Если вы не можете изменить входные данные, вы можете использовать рекурсивную функцию, которая будет суммировать все значения в списке списков (или на более глубоком уровне).

def sum_list(l):
    if isinstance(l, int):
        return l
    else:
        return sum(map(lambda x: sum_list(x), l))


scores = {10: [[1000], [1000]], 25: [[500], [500], [500]], 40: [[600]], 60: [[700]]}
result = {k: sum_list(v) for k,v in scores.items()}

print(result)

{10: 2000, 25: 1500, 40: 600, 60: 700}

...