Создайте словарь, сжав два списка разной длины

У меня есть два списка разной длины, L1 и L2. L1 длиннее L2. Я хотел бы получить словарь с членами L1 в качестве ключей и членами L2 в качестве значений.

Как только все члены L2 израсходованы. Я хотел бы начать все сначала и начать снова с L2 [0].

L1 = ['A', 'B', 'C', 'D', 'E']    
L2 = ['1', '2', '3']    
D = dict(zip(L1, L2))    
print(D)

Как и ожидалось, на выходе это:

{'A': '1', 'B': '2', 'C': '3'}

Я хотел бы добиться следующего:

{'A': '1', 'B': '2', 'C': '3', 'D': '1', 'E': '2'}

Ответ 1

Используйте itertools.cycle чтобы перейти к началу L2:

from itertools import cycle
dict(zip(L1, cycle(L2)))
# {'A': '1', 'B': '2', 'C': '3', 'D': '1', 'E': '2'}

В вашем случае объединение L2 с самим собой также работает.

# dict(zip(L1, L2 * 2))
dict(zip(L1, L2 + L2))
# {'A': '1', 'B': '2', 'C': '3', 'D': '1', 'E': '2'}

Ответ 2

Используйте itertools.cycle:

from itertools import cycle

L1 = ['A', 'B', 'C', 'D', 'E']
L2 = ['1', '2', '3']

result = dict(zip(L1, cycle(L2)))

print(result)

Выход

{'E': '2', 'B': '2', 'A': '1', 'D': '1', 'C': '3'}

В качестве альтернативы вы можете использовать перечисление и индекс L2 по модулю длины L2:

result = {v: L2[i % len(L2)] for i, v in enumerate(L1)}
print(result)

Ответ 3

cycle в порядке, но я добавлю этот подход по модулю:

{L1[i]: L2[i % len(L2)] for i in range(len(L1))]}

Ответ 4

Вы также можете использовать collections.deque() для создания циклической очереди FIFO:

from collections import deque

L1 = ['A', 'B', 'C', 'D', 'E']    
L2 = deque(['1', '2', '3'])

result = {}
for letter in L1:
    number = L2.popleft()
    result[letter] = number
    L2.append(number)

print(result)
# {'A': '1', 'B': '2', 'C': '3', 'D': '1', 'E': '2'}

Который выталкивает самый левый элемент, который в настоящее время находится в L2 и добавляет его в конец, как только число добавляется в словарь.

Примечание. Обе collections.deque.popleft() и collections.deque.append() являются операциями O (1), так что выше все равно O (N), так как вам нужно пройти все элементы в L1.

Ответ 5

Другой вариант без зависимостей с хорошим старым for цикла:

D = {}
for i, e in enumerate(L1):
  D[e] = L2[i%len(L2)]

D #=> {'A': '1', 'B': '2', 'C': '3', 'D': '1', 'E': '2'}

Или просто:

{ e: L2[i%len(L2)] for i, e in enumerate(L1) }
#=> {'A': '1', 'B': '2', 'C': '3', 'D': '1', 'E': '2'}