交错2个不等长度的列表

时间:2013-11-09 22:23:30

标签: python list for-loop indexing

我希望能够交错两个可能长度不等的列表。我所拥有的是:

  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

如何使用索引修复此问题?或者我必须使用for循环? 编辑:我想要的是让额外的值出现在最后。

4 个答案:

答案 0 :(得分:7)

您可以在此处使用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']

使用itertools中的roundrobin食谱,此处不需要哨兵值:

from itertools import *
def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # 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']

答案 1 :(得分:7)

您可以使用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 recipe来更有效地实现这一目标,而无需对项目进行比较。

答案 2 :(得分:2)

好的,这是我的参赛作品:

>>> 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工作,但它似乎并不像我希望的那样简单:事实证明我只是在努力重新实现圆形框架@hcwsha发布的食谱,所以完成它没有意义。 :^)]

答案 3 :(得分:0)

保持简单:

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
假设列表作为参数传递。