Сопоставление сумм defaultdict(list) в один список

У меня есть большая коллекция данных, отформатированных как d.items() из defaultdict(list). Смотри ниже:

products = [(('blue'), ([2, 4, 2, 4, 2, 4, 2, 4, 2, 4], [2, 4, 2, 4, 2, 4, 2, 4, 2, 4], [2, 4, 2, 4, 2, 4, 2, 4, 2, 4])),
        (('yellow'), ([1, 3, 1, 3, 1, 3, 1, 3, 1, 3], [1, 3, 1, 3, 1, 3, 1, 3, 1, 3], [1, 3, 1, 3, 1, 3, 1, 3, 1, 3])),
        (('red'), ([1, 1, 1, 1, 1, 2, 5, 4, 6, 4], [2, 5, 3, 4, 8, 1, 1, 1, 1, 1], [8, 6, 3, 9, 2, 1, 1, 1, 1, 1]))]

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

['blue', 6, 12, 6, 12, 6, 12, 6, 12, '6.000000', 12]
['yellow', 3, 9, 3, 9, 3, 9, 3, 9, '3.000000', 9]
['red', 11, 12, 7, 14, 11, 4, 7, 6, '8.000000', 6]

С циклами это можно легко сделать, как показано в этой функции:

def summation(products):

    sums = []

    for item in products:
            sums.append([(item[0]),
                     sum(int(x[0]) for x in item[1]),
                     sum(int(x[1]) for x in item[1]),
                     sum(int(x[2]) for x in item[1]),
                     sum(int(x[3]) for x in item[1]),
                     sum(int(x[4]) for x in item[1]),
                     sum(int(x[5]) for x in item[1]),
                     sum(int(x[6]) for x in item[1]),
                     sum(int(x[7]) for x in item[1]),
                     "{:.6f}".format(sum(float(x[8]) for x in item[1])),
                     sum(int(x[9]) for x in item[1])])

    for s in sums:
        print(s)

Проблема возникает, когда размер продукции исчисляется миллионами, т.е. это очень трудоемко. Поэтому я подумал о реализации сопоставления каждого значения с соответствующим во вложенном списке для того же ключа. Вот что я пробовал:

def mappingSum(products):
    sums = []

    for item in products:
        sums.append([item[0], map((sum(x), sum(y), sum(z)) for x, y, z in item[1])])



    for s in sums:
        print(s)

Однако я получаю следующую ошибку:

TypeError: map() must have at least two arguments.

Я не знаю, как решить эту проблему, и я не уверен, что map подходит для решения моей задачи.


person Mohammed    schedule 22.09.2016    source источник


Ответы (2)


Насколько я понимаю, вам нужно архивировать подсписки в списке и суммировать их:

>>> sums = [(key, [sum(value) for value in zip(*values)]) for key, values in products]
>>> for s in sums:
...     print(s)
... 
('blue', [6, 12, 6, 12, 6, 12, 6, 12, 6, 12])
('yellow', [3, 9, 3, 9, 3, 9, 3, 9, 3, 9])
('red', [11, 12, 7, 14, 11, 4, 7, 6, 8, 6])
person alecxe    schedule 22.09.2016

В качестве альтернативы ответу @alecxe рассмотрите следующее, используя map и хороший список literal-unpack:

res = [(k, [*map(sum, zip(*v))]) for k, v in products]

Это дает:

[('blue', [6, 12, 6, 12, 6, 12, 6, 12, 6, 12]),
 ('yellow', [3, 9, 3, 9, 3, 9, 3, 9, 3, 9]),
 ('red', [11, 12, 7, 14, 11, 4, 7, 6, 8, 6])]

Это немного быстрее, но требует Python >= 3.5 из-за буквальной распаковки. В более ранних версиях вам пришлось бы обернуть его вызовом list, чтобы распаковать итератор map:

res = [(k, list(map(sum, zip(*v)))) for k, v in products]
person Dimitris Fasarakis Hilliard    schedule 22.09.2016