python合并两个列表(偶数/奇数元素)

duc*_*cin 2 python merge list

给定两个列表,我想合并它们,以便第一个列表中的所有元素都是偶数索引(保留它们的顺序),第二个列表中的所有元素都是奇数索引(也保留它们的顺序).示例如下:

x = [0,1,2]
y = [3,4]

result = [0,3,1,4,2]
Run Code Online (Sandbox Code Playgroud)

我可以用for循环来做.但我想可能有一种奇特的pythonic方式(使用一个鲜为人知的函数或类似的东西).编写for循环有没有更好的解决方案?

编辑:我正在考虑列表推导,但到目前为止还没有提出任何解决方案.

Suk*_*lra 8

这是你可以使用的东西.(list(izip_longest(...))用于Py2x)

>>> from itertools import chain
>>> from itertools import zip_longest
>>> list(filter(lambda x: x != '', chain.from_iterable(zip_longest(x, y, fillvalue = ''))))
[0, 3, 1, 4, 2]
Run Code Online (Sandbox Code Playgroud)

这适用于任意长度列表,如下所示 -

>>> x = [0, 1, 2, 3, 4]
>>> y = [5, 6]
>>> list(filter(lambda x: x != '', chain.from_iterable(zip_longest(x, y, fillvalue = ''))))
[0, 5, 1, 6, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

解释它的工作 -

  1. zip_longest(...)对于不等长度的迭代,使用填充值来压缩列表并填充给定填充值.因此,对于您的原始示例,它评估为类似的东西[(0, 3), (1, 4), (2, '')]
  2. 我们需要展平结果,因为这个方法为我们提供了一个元组列表.为此,我们使用chain.from_iterable(...)给我们类似的东西[0, 3, 1, 4, 2, ''].
  3. 我们现在filter(...)用来删除所有出现的'',我们得到了所需的答案.


Sau*_*tro 6

你可以简单地做:

for i,v in enumerate(y):
    x.insert(2*i+1,v)
Run Code Online (Sandbox Code Playgroud)

这利用了插入时将使用最后一个索引的优势。

一个例子:

x = [0,1,2,3,4,5]
y = [100, 11,22,33,44,55,66,77]
print x
# [0, 100, 1, 11, 2, 22, 3, 33, 4, 44, 5, 55, 66, 77]
Run Code Online (Sandbox Code Playgroud)

  • @tkoomzaaskz `list.insert` 是一个 O(N) 操作。 (3认同)
  • 我喜欢这个,因为它很简单——唯一要解决的就是不要修改 x。`import copy`/`res = copy.copy(x)`/`for i,v in enumerate(y):`/`res.insert(2*i+1,v)` (2认同)
  • @tkoomzaaskz :只是一些 `timeit` 结果。(设置 - 两个列表,长度为 100 之一,长度为 50 之一,迭代次数 = 5000,**Py2x**)Saullo 的解决方案 - `44.59869242355262`,Ashwini 的解决方案 - `0.36575645629210385`,我的解决方案 -`6531 Nio 的解决方案 - `0.21236540710697227`。 (2认同)

nio*_*nio 5

尝试这个:

x = [0,1,2,10,11]
y = [3,4]

n =  2*max([len(x),len(y)])
res = n *[None]
res[:2*len(x):2] = x
res[1:2*len(y):2] = y
res = [x for x in res if x!=None]
print res
Run Code Online (Sandbox Code Playgroud)

它应该适用于不均匀长的列表。


Ash*_*ary 5

使用roundrobin 配方itertools:

from itertools import cycle, islice
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(x,y))
[0, 3, 1, 4, 2]
Run Code Online (Sandbox Code Playgroud)


Sep*_*ero 5

如果你有相同长度的列表,你可以使用这个:

result = [ item for tup in zip(x,y) for item in tup ]
Run Code Online (Sandbox Code Playgroud)