с помощью Python уменьшить список пар

Я пытаюсь соединить кучу элементов в списке, чтобы создать конечный объект, аналогично созданию суммы объектов. Я пытаюсь использовать простую вариацию reduce, где для этого вы рассматриваете список пар, а не плоский список. Я хочу сделать что-то вроде:

nums = [1, 2, 3]
reduce(lambda x, y: x + y, nums)

за исключением того, что я хотел бы добавить дополнительную информацию к сумме, относящейся к каждому элементу в списке чисел nums. Например, для каждой пары (a,b) в списке запустите сумму как (a+b):

nums = [(1, 0), (2, 5), (3, 10)]
reduce(lambda x, y: (x[0]+x[1]) + (y[0]+y[1]), nums)

Это не работает:

>>> reduce(lambda x, y: (x[0]+x[1]) + (y[0]+y[1]), nums)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
TypeError: 'int' object is unsubscriptable

Почему это не работает? Я знаю, что могу кодировать nums как плоский список - это не главное - я просто хочу иметь возможность создать операцию сокращения, которая может выполнять итерацию по списку пар или по двум спискам одинаковой длины одновременно и объединять информацию из оба списка. Спасибо.


person Community    schedule 21.10.2012    source источник
comment
Вы хотите, чтобы результатом сокращения был кортеж?   -  person Vaughn Cato    schedule 21.10.2012
comment
Вы должны использовать сокращение? Я предпочитаю простую сумму (x[0] + x[1] для x в цифрах)   -  person cerealy    schedule 21.10.2012


Ответы (1)


Глядя на лямбду, которую вы передали reduce:

f = lambda x, y: (x[0]+x[1]) + (y[0]+y[1])

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

>>> nums = [(1, 0), (2, 5), (3, 10)]
>>> reduce(lambda x, y: (x[0] + y[0], x[1] + y[1]), nums)
(6, 15)

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

>>> nums = [(1, 0), (2, 5), (3, 10)]
>>> reduce(lambda acc, y: acc + y[0] + y[1], nums, 0)
21
person interjay    schedule 21.10.2012
comment
Есть ли способ просто получить итератор от сокращения по парам? Что-то похожее на enumerate(mylist) для списков, где возвращает не только текущий элемент, но и его позицию в списке. Может ли lambda в reduce получить доступ к номеру пары, используемой в приведенном выше примере? - person ; 21.10.2012
comment
@ user248237 Вы можете использовать enumerate(mylist) в качестве входных данных для reduce. - person interjay; 21.10.2012