【问题标题】:python merge two lists (even/odd elements)python合并两个列表(偶数/奇数元素)
【发布时间】:2013-08-05 04:43:12
【问题描述】:

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

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

result = [0,3,1,4,2]

我可以使用 for 循环来做到这一点。但我想可能有一种花哨的pythonic方式来做到这一点(使用一个鲜为人知的函数或类似的东西)。有没有比写for循环更好的解决方案?

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

【问题讨论】:

  • 你想为x=[0,1,2,3,4,5,6]y=[20,21] 做什么,或者相反? (即,如果一个列表比另一个更长或更短怎么办?)
  • 假设更简单的情况:len(x) == len(y) OR len(x) == len(y) + 1,所以不用担心。这将是游戏的一系列动作。
  • 在这种情况下,请使用roundrobin 或简化版本。
  • @nio 你为什么删除你的答案?到目前为止我最喜欢它(最短和最简单的)
  • @torek,如果列表更长或更短,则以下答案中建议的方法有效...

标签: python list merge


【解决方案1】:

这里有一些你可以使用的东西。 (对 Py2x 使用 list(izip_longest(...))

>>> 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]

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

>>> 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]

解释它的工作原理 -

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

【讨论】:

  • 对于 len(x)=len(y)+1:list(chain.from_iterable(zip(x,y))) + [x[-1]]
【解决方案2】:

你可以这样做:

for i,v in enumerate(y):
    x.insert(2*i+1,v)

这利用了insert在被越过时会使用最后一个索引。

一个例子:

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]

【讨论】:

  • 我喜欢这个,因为它很简单——唯一需要解决的就是不要修改 x。 import copy/res = copy.copy(x)/for i,v in enumerate(y):/res.insert(2*i+1,v)
  • @tkoomzaaskz list.insert 是一个 O(N) 操作。
  • @AshwiniChaudhary 你的意思是复杂性?所以呢? (对不起,如果我不明白你的意思)
  • @tkoomzaaskz 是的复杂性,为了将每个项目插入x,它将执行O(N) 步骤。所以,这个解决方案的整体复杂度是O(len(y) * len(x)),而其他解决方案只是O(len(x) + len(y))。对于大型列表,这将非常缓慢。
  • @tkoomzaaskz :只是一些timeit 结果。 (设置 - 两个列表,一个长度为 100,一个长度为 50,迭代 = 5000,Py2x)Saullo 的解决方案 - 44.59869242355262,Ashwini 的解决方案 - 0.36575645629210385,我的解决方案 - 0.5685753073638011。 Nio 的解决方案 - 0.21236540710697227.
【解决方案3】:

使用来自itertoolsroundrobin recipe

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]

【讨论】:

    【解决方案4】:

    试试这个:

    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
    

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

    【讨论】:

      【解决方案5】:

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

      result = [ item for tup in zip(x,y) for item in tup ]
      

      【讨论】:

        【解决方案6】:

        这很简单,虽然不如roundrobin灵活:

        def paired(it1, it2):
            it2 = iter(it2)
            for item in it1:
                yield item
                yield next(it2)
        

        在 2.7.5 中测试:

        >>> x = [0, 1, 2]
        >>> y = [3, 4]
        >>> print list(paired(x, y))
        [0, 3, 1, 4, 2]
        

        请注意,一旦列表 y 用完,它就会停止(因为 next(it2) 会引发 StopIteration)。

        【讨论】:

        • 是的,但是 - 正如我在问题中所写的 - 我可以只使用 for 循环来做到这一点。我在考虑一些基于语法的东西(比如列表切片或列表推导)。无论如何,谢谢
        • 这会遗漏一些项目:paired(y,x).
        • @AshwiniChaudhary:这就是为什么我在上面询问当一个列表比另一个列表长时该怎么办。
        【解决方案7】:

        可以通过切片来完成。在终端中执行countslice

        >>> list1=['Apple','Mango','Orange']
        >>> list2=['One','Two','Three']
        >>> list = [None]*(len(list1)+len(list2))
        >>> list[::2] = list1
        >>> list[1::2] = list2
        >>> list
        

        输出:

         ['Apple', 'One', 'Mango', 'Two', 'Orange', 'Three']
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-09-01
          • 1970-01-01
          • 2020-01-03
          • 2017-02-06
          • 1970-01-01
          • 2021-06-13
          • 2021-07-18
          • 2019-04-28
          相关资源
          最近更新 更多