Попытка понимания списка Python с двумя переменными разных диапазонов

Я пытаюсь быстро создать список с содержимым из двух разных массивов размером n и n/2. В качестве примера:

A = [70, 60, 50, 40, 30, 20, 10, 0]
B = [1, 2, 3, 4]

Я хочу создать нечто вроде

[(A[x], B[y]) for x in range(len(A)) for y in range(len(B))]

Я понимаю, что второй оператор for является вложенным циклом после "x". Я пытаюсь получить содержимое нового массива

A[0], B[0]
A[1], B[1]
A[2], B[2]
A[3], B[3]
A[4], B[0]
A[5], B[1]
A[6], B[2]
A[7], B[3]

Может ли кто-нибудь указать мне в правильном направлении?

Ответ 1

Не использовать вложенные циклы; вы соединяете A и B, при этом B повторяется по мере необходимости. Вам нужно zip() (чтобы сделать сопряжение) и itertools.cycle() (повторить B):

from itertools import cycle

zip(A, cycle(B))

Если B всегда будет в два раза меньше A, вы также можете просто удвоить B:

zip(A, B + B)

Демо:

>>> from itertools import cycle
>>> A = [70, 60, 50, 40, 30, 20, 10, 0]
>>> B = [1, 2, 3, 4]
>>> zip(A, cycle(B))
[(70, 1), (60, 2), (50, 3), (40, 4), (30, 1), (20, 2), (10, 3), (0, 4)]
>>> zip(A, B + B)
[(70, 1), (60, 2), (50, 3), (40, 4), (30, 1), (20, 2), (10, 3), (0, 4)]

В тех случаях, когда неизвестно, какой из них является более длинным списком, вы можете использовать min() и max(), чтобы выбрать, какой из циклов:

zip(max((A, B), key=len), cycle(min((A, B), key=len))

или для произвольного количества списков, чтобы скомпилировать их, используйте их itertools.islice(), чтобы ограничить максимальную длину:

inputs = (A, B)  # potentially more
max_length = max(len(elem) for elem in inputs)
zip(*(islice(cycle(elem), max_length) for elem in inputs))

Демо:

>>> from itertools import islice
>>> inputs = (A, B)  # potentially more
>>> max_length = max(len(elem) for elem in inputs)
>>> zip(*(islice(cycle(elem), max_length) for elem in inputs))
[(70, 1), (60, 2), (50, 3), (40, 4), (30, 1), (20, 2), (10, 3), (0, 4)]

Ответ 2

[(A[x % len(A)], B[x % len(B)]) for x in range(max(len(A), len(B)))]

Это будет работать независимо от того, является ли A более крупным.:)

Ответ 3

Попробуйте использовать только один цикл for вместо двух и второй обернуть назад до 0 после того, как он пройдет его длину.

[(A[x], B[x%len(B)]) for x in range(len(A))]

Обратите внимание, что это будет работать, только если A - более длинный список. Если вы знаете, что B всегда будет в два раза меньше A, вы также можете использовать это:

list(zip(A, B*2))