почтовый список с одним элементом

У меня есть список некоторых элементов, например, [1, 2, 3, 4] и одного объекта, например, 'a'. Я хочу создать список кортежей с элементами списка в первой позиции и единственным объектом во второй позиции: [(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')].

Я мог бы сделать это с zip как это:

def zip_with_scalar(l, o): # l - the list; o - the object
    return list(zip(l, [o] * len(l)))

Однако это дает мне ощущение создания и ненужного списка повторяющихся элементов.

Другая возможность

def zip_with_scalar(l, o):
    return [(i, o) for i in l]

что действительно очень чисто и питонично, но здесь я делаю все это "вручную". В Хаскеле я бы сделал что-то вроде

zipWithScalar l o = zip l $ repeat o

Существует ли какая-либо встроенная функция или прием, либо для архивирования со скаляром, либо для чего-то, что позволило бы мне использовать обычный zip, то есть бесконечный список?

Ответ 1

Это самое лучшее для вашего решения Haskell:

import itertools

def zip_with_scalar(l, o):
    return zip(l, itertools.repeat(o))

Вы также можете использовать генераторы, которые не позволяют создавать список, например, как понимание:

def zip_with_scalar(l, o):
    return ((i, o) for i in l)

Ответ 2

Вы можете использовать встроенную функцию map:

>>> elements = [1, 2, 3, 4]
>>> key = 'a'
>>> map(lambda e: (e, key), elements)
[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')]

Ответ 3

Это идеальная работа для класса itertools.cycle.

from itertools import cycle


def zip_with_scalar(l, o):
    return zip(i, cycle(o))

Демо:

>>> from itertools import cycle
>>> l = [1, 2, 3, 4]
>>> list(zip(l, cycle('a')))
[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')]

Ответ 4

lst = [1,2,3,4]
tups = [(itm, 'a') for itm in lst]
tups

> [(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')]

Ответ 5

Вы также можете использовать zip_longest с fillvalue o:

from itertools import zip_longest

def zip_with_scalar(l, o): # l - the list; o - the object
    return zip_longest(l, [o], fillvalue=o)

print(list(zip_with_scalar([1, 2, 3, 4] ,"a")))

Просто помните, что любые изменяемые значения, используемые для o, не будут скопированы с использованием zip_longest или repeat.

Ответ 6

Просто определите класс с бесконечным итератором, который инициализируется единственным элементом, который вы хотите добавить в списки:

class zipIterator:
    def __init__(self, val):
        self.__val = val

    def __iter__(self):
        return self

    def __next__(self):
        return self.__val

а затем создайте свой новый список из этого класса и списки, которые у вас есть:

elements = [1, 2, 3, 4]
key = 'a'
res = [it for it in zip(elements, zipIterator(key))]

результат будет:

>>res
[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')]