如何将可迭代拆分为两个具有交替元素的列表

Posted

技术标签:

【中文标题】如何将可迭代拆分为两个具有交替元素的列表【英文标题】:How to split an iterable into two lists with alternating elements 【发布时间】:2010-11-29 09:23:16 【问题描述】:

我想将一个可迭代对象拆分为两个具有交替元素的列表。这是一个有效的解决方案。但是有没有更简单的方法来达到同样的效果?

def zigzag(seq):
    """Return two sequences with alternating elements from `seq`"""
    x, y = [], []
    p, q = x, y
    for e in seq:
        p.append(e)
        p, q = q, p
    return x, y

样本输出:

>>> zigzag('123456')
(['1', '3', '5'], ['2', '4', '6'])

【问题讨论】:

【参考方案1】:

如果seq是一个序列,那么:

def zigzag(seq):
  return seq[::2], seq[1::2]

如果seq 是一个完全通用的可迭代对象,比如可能是一个生成器:

def zigzag(seq):
  results = [], []
  for i, e in enumerate(seq):
    results[i%2].append(e)
  return results

【讨论】:

@Sridhar,不要认为它是懒惰的,认为它是省时。我花了半个小时研究一个算法,用一个 for 循环(对于 x 列,而不仅仅是两个)来做到这一点。虽然我得到了它的工作,但它似乎并不 pythonic - 我怀疑有一个更简单的方法。果然,我不记得列表有 step 变量(如本答案所示),这使它变得微不足道。【参考方案2】:

这需要一个迭代器并返回两个迭代器:

import itertools
def zigzag(seq):
    t1,t2 = itertools.tee(seq)
    even = itertools.islice(t1,0,None,2)
    odd = itertools.islice(t2,1,None,2)
    return even,odd

如果您更喜欢列表,那么您可以return list(even),list(odd)

【讨论】:

【参考方案3】:
def zigzag(seq):
    return seq[::2], seq[1::2]

【讨论】:

仅适用于列表,而其他解决方案适用于任何可迭代对象。 是的,但标题确实指定了一个列表【参考方案4】:

我只是想清除一些东西。假设你有一个列表

list1 = list(range(200))

你可以做任何一个:

## OPTION A ##
a = list1[1::2]
b = list1[0::2]

## OPTION B ##
a = list1[0:][::2] # even
b = list1[1:][::2] # odd

并且在变量ab中有替代元素。

但是OPTION A的速度是原来的两倍

【讨论】:

以上是关于如何将可迭代拆分为两个具有交替元素的列表的主要内容,如果未能解决你的问题,请参考以下文章

将列表拆分为 2 个相等和的列表

Python:当列表仅在运行时确定时,如何将可迭代列表传递给 zip?

如何迭代具有两个不同标准的列表?

交替附加两个列表中的元素

如何合并、拆分和查询第 k 个排序列表?

将列表拆分为两个列表的所有可能性