Python 交错2个长度不等的列表

Python 交错2个长度不等的列表,python,list,for-loop,indexing,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

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

  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循环? 编辑:我想让额外的值只出现在末尾。

您可以在此处使用:

使用来自的循环配方,此处不需要sentinel值:

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))
演示:

您可以在此处使用:

使用来自的循环配方,此处不需要sentinel值:

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))
演示:

您可以使用heapq.merge:

这样就避免了对sentinel值和平坦化的需要

请改用,以更有效地实现这一点,而不使项目具有可比性。

您可以使用heapq.merge:

这样就避免了对sentinel值和平坦化的需要

相反,使用更有效的方法来实现这一点,而无需让项目具有可比性。

好的,下面是我的条目:

>>> 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)
这也行得通,这就是@hcwhsa使用的listcomp扁平化的习惯用法。我的第一个想法是

>>> list(zip(*sorted(list(enumerate(xs)) + list(enumerate(ys)))))[1]
(1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why')
但这只是@Jon Clements的一个效率低得多的版本。我使用了一个效率低的排序,他使用了一个高效的堆队列

[我一直在尝试使用cycle working获得一些东西,但似乎并不像我希望的那么简单:结果证明我只是在努力重新实现@hcwsha发布的循环食谱,所以没有必要完成它。:^]

好的,这是我的条目:

>>> 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)
这也行得通,这就是@hcwhsa使用的listcomp扁平化的习惯用法。我的第一个想法是

>>> list(zip(*sorted(list(enumerate(xs)) + list(enumerate(ys)))))[1]
(1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why')
但这只是@Jon Clements的一个效率低得多的版本。我使用了一个效率低的排序,他使用了一个高效的堆队列

[我一直在尝试使用cycle working获得一些东西,但似乎并不像我希望的那么简单:而且事实证明,我只是在努力重新实现@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 假设列表作为参数传递。

保持简单:

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

假设列表作为参数传递。

您希望发生什么?输出应该是什么?@DavidRobinson我想做的是在末尾显示额外的值。那么[1,嗨,2,再见,3,不,是的,为什么]?@DavidRobinson是的,这是一个测验问题吗?你想发生什么?输出应该是什么?@DavidRobinson我想做的是让额外的值出现在末尾。那么[1,嗨,2,再见,3,不,是的,为什么]?@DavidRobinson是的,这是一个测验问题吗?我有一个zip函数,我制作了它来压缩X和Y。我可以用它来代替吗?@user2829177 izip_longest与zip稍有不同,zip将输出截短到最短的列表。有更简单的方法吗?@user2829177您可能会发现itertools中的循环法有点帮助。我已经在我的回答中发布了。@user2829177查看DSM的第一个解决方案,IMO这是最简单的方法。我有一个zip函数,我制作了它,可以将xs和ys分开。我可以用它来代替吗?@user2829177 izip_longest与zip稍有不同,zip将输出截短到最短的列表。有更简单的方法吗?@user2829177您可能会发现itertools中的循环法有点帮助。我已经在我的回答中发布了。@user2829177查看DSM的第一个解决方案,IMO这是最简单的方法。实际上,我们正在Python房间里讨论这一点-在Python 3.x上,我们的方法会因为需要进行比较而中断…:@乔恩·克莱门茨:嘿,我的官方条目会有效的,那里没有比较^是 啊我注意到我还重新编写了一个非itertools版本的roundrobin:我们实际上在Python房间里聊了一会儿——在Python 3.x上,我们的方法会因为需要进行比较而中断@乔恩·克莱门茨:嘿,我的官方条目会有效的,那里没有比较^是 啊我注意到我还重新编写了一个非itertools版本的循环:我认为您的out+=xs[index]+ys[index]行需要是out+=[xs[index],ys[index]],或者使用单元素切片或其他方法来确保连接列表。Python3中没有xrange。但是这些问题很容易解决。@DSM,我在一个测试用例上尝试了它,它工作了,interleavelist'ab',list'cdefghijklmnop'。我应该声明我的答案是Python 2吗?这里是否有一个假设,除非另有说明,否则答案是3?您的测试用例有点特殊,因为它们是一个字符串。试试[1,2,3]和['hi','bye','no','yes','why'],甚至['ab','cd','ef','gh']。至于Python3,我很抱歉-我确信这个问题有Python3标记,但它似乎没有。谢谢你的提示。固定的当修理
如果我不允许使用除len、range、list、str、print和.append以外的任何函数,该怎么办?我有一个求最小值的函数,所以我修正了它。但我不明白如何替换.extend@wwiiI。我认为您的out+=xs[index]+ys[index]行需要是out+=[xs[index],ys[index]],或者使用单元素切片或其他方法来确保连接列表。Python3中没有xrange。但是这些问题很容易解决。@DSM,我在一个测试用例上尝试了它,它工作了,interleavelist'ab',list'cdefghijklmnop'。我应该声明我的答案是Python 2吗?这里是否有一个假设,除非另有说明,否则答案是3?您的测试用例有点特殊,因为它们是一个字符串。试试[1,2,3]和['hi','bye','no','yes','why'],甚至['ab','cd','ef','gh']。至于Python3,我很抱歉-我确信这个问题有Python3标记,但它似乎没有。谢谢你的提示。固定的在修复时,提醒我已经看到了一些东西。如果不允许我使用除:len、range、list、str、print和.append以外的任何函数,该怎么办?我有一个求最小值的函数,所以我修正了它。但我不明白如何替换.extend@wwiit,因为它已经深入到我的思想中,不修改使用for循环迭代的序列的内容。如果你不知道自己在做什么,就不要这样做?我想弄明白为什么这个发电机没问题,有什么提示吗?@wwii这不是个好主意。把这归咎于晚上11点的一篇累帖。它将适用于2个序列。然而,对于连续等长的一个较短的一个之前-下一个项目的顺序变得不稳定-使用roundroubin配方是正确的方法做到这一点。。。我已经删除了代码,并更新了相应的答案。我被灌输了不修改使用for循环迭代的序列内容的思想。如果你不知道自己在做什么,就不要这样做?我想弄明白为什么这个发电机没问题,有什么提示吗?@wwii这不是个好主意。把这归咎于晚上11点的一篇累帖。它将适用于2个序列。然而,对于连续等长的一个较短的一个之前-下一个项目的顺序变得不稳定-使用roundroubin配方是正确的方法做到这一点。。。我已经删除了代码并更新了相应的答案。