#python #list
Вопрос:
У меня есть три списка:
list_01 = ['DOG','CAT','BEAR']
list_02 = ['V','W','X','Y','Z']
list_03 = ['A','B','C','D','E','F','G','H']
То, что я надеюсь получить, — это список, подобный следующему:
list_04 = ['DOG','V','A','CAT','W','B','BEAR','X','C','Y','D','Z','E','F','G','H']
Предполагается, что этот список должен содержать один элемент из списка 1, затем один из списка 2 и один из списка 3. Затем это продолжается до тех пор, пока список 1 не будет исчерпан; затем список 1 следует игнорировать, и тот же процесс должен происходить только в списках 2 и 3, продолжаясь до тех пор, пока все списки не опустеют.
Ответ №1:
Похоже, вы хотите сделать это по порядку, а не случайным образом. Если это так, вы можете использовать zip_longest()
из itertools и сделать понимание вложенного списка:
from itertools import zip_longest
list_01 = ['DOG','CAT','BEAR']
list_02 = ['V','W','X','Y','Z']
list_03 = ['A','B','C','D','E','F','G','H']
list_04 = [n for group in zip_longest(list_01, list_02, list_03)
for n in group if n is not None]
# ['DOG', 'V', 'A', 'CAT', 'W', 'B', 'BEAR', 'X', 'C', 'Y', 'D', 'Z', 'E', 'F', 'G', 'H']
Примечание: zip_longest
будет генерировать None
значения, когда закончится один список. Вот почему мы ищем в понимании. None
Ответ №2:
Вы можете использовать zip_longest
и chain
из itertools
модуля:
from itertools import chain, zip_longest
list_04 = [i for i in chain(*zip_longest(list_01, list_02, list_03))
if i is not None]
выход:
['DOG', 'V', 'A', 'CAT', 'W', 'B', 'BEAR', 'X', 'C', 'Y', 'D', 'Z', 'E', 'F', 'G', 'H']
Комментарии:
1. Это удалит все ложные значения, а не только ни одного, что может быть проблемой для OP.
2. @AKX Я видел у тебя интересную альтернативу. Я не склонен преждевременно оптимизировать, пример OP, похоже, указывает на то, что никаких ложных значений не ожидается 😉
3. Кстати, как обращаться со случаями, когда один из списков не содержит ни одного?
4. @eroot163pi Вы можете использовать
fillvalue=XXX
zip_longest
с чем-то, что, как вы знаете, не будет соответствовать, и вместо этого проверить равенство с этим.5. @eroot163pi проверьте итератор AKX, вот что он делает
Ответ №3:
Самый простой способ:
result = list(roundrobin(list_01, list_02, list_03))
Просто скопируйте и вставьте roundrobin
из рецептов Itertools или импортируйте их из more-itertools (как указано в разделе рецепты).
В качестве альтернативы мне нравится использовать heapq.merge
:
result = list(map(itemgetter(1), merge(*map(enumerate, lists), key=itemgetter(0))))
Вариант:
index, value = map(itemgetter, (0, 1))
result = list(map(value, merge(*map(enumerate, lists), key=index)))
Полный код (попробуйте онлайн!):
from operator import itemgetter
from heapq import merge
list_01 = ['DOG','CAT','BEAR']
list_02 = ['V','W','X','Y','Z']
list_03 = ['A','B','C','D','E','F','G','H']
lists = list_01, list_02, list_03
expect = ['DOG','V','A','CAT','W','B','BEAR','X','C','Y','D','Z','E','F','G','H']
result = list(map(itemgetter(1), merge(*map(enumerate, lists), key=itemgetter(0))))
print(result == expect)
index, value = map(itemgetter, (0, 1))
result = list(map(value, merge(*map(enumerate, lists), key=index)))
print(result == expect)
Ответ №4:
Вы можете использовать more_itertools.interleave_longest
:
>>> from more_itertools import interleave_longest
>>> list(interleave_longest(
... ['DOG','CAT','BEAR'],
... ['V','W','X','Y','Z'],
... ['A','B','C','D','E','F','G','H'],
... ))
['DOG', 'V', 'A', 'CAT', 'W', 'B', 'BEAR', 'X', 'C', 'Y', 'D', 'Z', 'E', 'F', 'G', 'H']
Ответ №5:
list_01 = ['DOG','CAT','BEAR']
list_02 = ['V','W','X','Y','Z']
list_03 = ['A','B','C','D','E','F','G','H']
L = [list_01, list_02, list_03]
def shuffle(L):
result = []
while any(L):
for sub in L:
if sub:
result.append(sub.pop(0))
return result
print(shuffle(L))
Выход:
['DOG', 'V', 'A', 'CAT', 'W', 'B', 'BEAR', 'X', 'C', 'Y', 'D', 'Z', 'E', 'F', 'G', 'H']
Комментарии:
1. Вы имеете в виду, не помещая вложенные списки в другой список?
2. Я обновил свое решение. Я думаю, проблема заключалась в том, что я удалил из списка, повторяя его, что создало некоторые неприятные побочные эффекты.
Ответ №6:
Вы можете использовать функцию zip
list_01 = ['DOG','CAT','BEAR']
list_02 = ['V','W','X','Y','Z']
list_03 = ['A','B','C','D','E','F','G','H']
minimum_size = min(len(list_01) , len(list_02) , len(list_03))
new_array = []
for item1 , item2 , item3 in zip(list_01 , list_02 , list_03):
new_array.extend([item1 , item2 , item3])
new_array = list_01[minimum_size:] list_02[minimum_size:] list_03[minimum_size:]
print(new_array)
Комментарии:
1. Это не работает корректно для списков разной длины
Ответ №7:
Редактировать: в этом ответе списки объединяются неупорядоченным образом, что не совсем то, что хотел ОП.
Используется itertools.chain
для объединения списков в один список, а затем random.shuffle
для перемешивания этого списка на месте:
from itertools import chain
from random import shuffle
list_01 = ['DOG','CAT','BEAR']
list_02 = ['V','W','X','Y','Z']
list_03 = ['A','B','C','D','E','F','G','H']
full_list = list(chain(list_01, list_02, list_03))
shuffle(full_list)
print(full_list) # in my case: ['BEAR', 'V', 'Z', 'W', 'A', 'Y', 'E', 'G', 'CAT', 'B', 'X', 'H', 'D', 'F', 'DOG', 'C']
Комментарии:
1. Идея заключается не в том, чтобы перетасовать их, а выбрать по порядку.
2. @AKX Ах, понятно, я не понял этого из вопроса. Не уверен, что мне следует удалить свой ответ, но я, по крайней мере, отредактирую его и добавлю предупреждение.
Ответ №8:
Используя простой python(без numpy), это лучшее, что я мог придумать.
Я считаю, что это работает для любого порядка, длины списков и не предполагает значения fill_value
list_01 = ['DOG','CAT','BEAR']
list_02 = ['V','W','X','Y','Z']
list_03 = ['A','B','C','D','E','F','G','H']
L = [list_01, list_03, list_02]
def zigzag(*arg):
i = 0
LL = []
all_done = False
while not all_done:
all_done = True
for l in arg:
if i >= len(l):
continue
all_done = False
LL.append(l[i])
i = 1
return LL
print(zigzag(list_01, list_02, list_03))
print(zigzag(list_01, list_03, list_02))