Использование zip_longest для суммирования списков разной длины и заполнения разной длины от начала, а не до конца - PullRequest
0 голосов
/ 14 января 2019

У меня есть два списка [1,2,3,4] и [1,2,3]

Я хотел бы суммировать их, чтобы дать мне следующее: [1,3,5,7].

Это было сделано с помощью 1+0=1, 2+1=3, 3+2=5 и 4+3=7.

Я понимаю, что itertools.zip_longest будет делать это, но оно заполнит несоответствие по длине с 0 в конце, давая мне [2,3,6,4], а не значение, которое я хочу.

Я бы хотел, чтобы рассогласование по длине было решено путем заполнения первой длины нулем.

Ответы [ 5 ]

0 голосов
/ 14 января 2019

Встроенная функция reversed() может использоваться для этого следующим образом:

from itertools import zip_longest    

def sum_lists(*iterables):
    iterables = (reversed(it) for it in iterables)
    return list(reversed([a+b for a, b in zip_longest(*iterables, fillvalue=0)]))


if __name__ == '__main__':
    result = sum_lists([1, 2, 3, 4], [1, 2, 3])
    print(result)  # -> [1, 3, 5, 7]
    result = sum_lists([1, 2, 3], [1, 2, 3, 4])
    print(result)  # -> [1, 3, 5, 7]    # Order of args doesn't matter.
0 голосов
/ 14 января 2019

Вы можете построить сдвиг , используя повтор , а затем объединить сдвиг с более коротким, используя цепочка :

from itertools import repeat, chain

first = [1, 2, 3, 4]
second = [1, 2, 3]

shift = repeat(0, abs(len(first) - len(second)))

result = [a + b for a, b in zip(first, chain(shift, second))]

print(result)

выход

[1, 3, 5, 7]
0 голосов
/ 14 января 2019

Вы можете обойти эту проблему, если бы изменили свои списки до zip с zip_longest.

from itertools import zip_longest

s1, s2 = [1,2,3,4], [1, 2, 3]
res = [a+b for a, b in zip_longest(reversed(s1), reversed(s2), fillvalue=0)]

и, наконец, снова , чтобы получить желаемый результат:

res = res[::-1]
print(res)  # [1, 3, 5, 7]

Основное преимущество этого метода, как говорит @CoryKramer в своем комментарии, заключается в том, что вам не нужно заранее знать, какой список самый длинный.

0 голосов
/ 14 января 2019

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

from itertools import zip_longest
lists = [1,2,3,4], [1, 2, 3]
print(list(map(sum, zip_longest(*map(reversed, lists), fillvalue=0)))[::-1])

Это выводит:

[1, 3, 5, 7]
0 голосов
/ 14 января 2019

Вы можете дополнить второй список нулями и использовать zip:

s1, s2 = [1,2,3,4], [1, 2, 3]
new_result = [a+b for a, b in zip(s1, ([0]*(len(s1)-len(s2)))+s2)]

Выход:

[1, 3, 5, 7]
...