чередование 2 списков неравных длин

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

def interleave(xs,ys): a=xs b=ys c=a+b c[::2]=a c[1::2]=b return c 

Это отлично работает со списками, которые равны по длине или просто +/- 1. Но если скажем xs = [1,2,3] и ys = ["hi," bye "," no "," yes "," why "] это сообщение появляется:

 c[::2]=a ValueError: attempt to assign sequence of size 3 to extended slice of size 4 

Как исправить это с помощью индексации? или я должен использовать для циклов? EDIT: я хочу, чтобы дополнительные значения отображались только в конце.

4 Solutions collect form web for “чередование 2 списков неравных длин”

Вы можете использовать itertools.izip_longest здесь:

 >>> from itertools import izip_longest >>> xs = [1,2,3] >>> ys = ["hi","bye","no","yes","why"] >>> s = object() >>> [y for x in izip_longest(xs, ys, fillvalue=s) for y in x if y is not s] [1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why'] 

Используя рецепт roundrobin от itertools , здесь не требуется значение дозорности :

 from itertools import * def roundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> ADEBFC" # Recipe credited to George Sakkis pending = len(iterables) nexts = cycle(iter(it).next for it in iterables) while pending: try: for next in nexts: yield next() except StopIteration: pending -= 1 nexts = cycle(islice(nexts, pending)) 

Демоверсия:

 >>> list(roundrobin(xs, ys)) [1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why'] >>> list(roundrobin(ys, xs)) ['hi', 1, 'bye', 2, 'no', 3, 'yes', 'why'] 

Вы можете использовать heapq.merge :

 xs = [1, 2, 3] ys = ['hi', 'bye', 'no', 'yes', 'why'] import heapq interleaved = [v for i, v in heapq.merge(*[enumerate(el) for el in (xs, ys)])] # [1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why'] 

Это позволяет избежать необходимости получения дозорного значения и сглаживания.

Вместо этого используйте рецепт roundrobin, чтобы достичь этого более эффективно, не имея сопоставимых предметов.

Хорошо, вот моя запись:

 >>> from itertools import chain >>> xs = [1,2,3] >>> ys = ["hi","bye","no","yes","why"] >>> xi, yi = iter(xs), iter(ys) >>> list(chain.from_iterable(zip(xi, yi))) + list(xi) + list(yi) [1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why'] 

С другой стороны,

 >>> [i for row in zip(xi, yi) for i in row] + list(xi) + list(yi) 

(это просто идентификатор listcomp для выравнивания, используемый @hcwhsa). Моя первая мысль была

 >>> list(zip(*sorted(list(enumerate(xs)) + list(enumerate(ys)))))[1] (1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why') 

но это всего лишь менее эффективная версия @Jon Clements (я использовал неэффективную сортировку, он использовал эффективную очередь кучи).

[Я экспериментировал с попыткой получить что-то, используя cycle , но мне кажется, это не так просто, как я надеялся: и получается, что я просто работал над повторением рецепта roundrobin, который был отправлен @hcwsha, поэтому нет смысла заканчивать это. : ^)]

Это было просто:

 def interleave(xs,ys): stop = min(len(xs), len(ys)) suffix = max(xs, ys, key = len)[stop:] out = list() for pair in zip(xs, ys): out.extend(pair) out.extend(suffix) return out 

Предостережения:
Python 2.7
Предполагается, что в качестве аргументов передаются списки.

  • Ускорить цикл в свертке для numpy 3D-массива?
  • Python - Любой способ избежать нескольких if-утверждений внутри друг друга в for-loop?
  • Питоновская итерация по нескольким спискам параллельно
  • как перезапустить цикл for for python?
  • Как я могу создать произвольный генератор кода hexdigit с использованием .join и для циклов?
  • For-loops в Python
  • Для цикла с несколькими условиями в Python
  • Избегание вложенных циклов
  • Python - лучший язык программирования в мире.