【问题标题】:Round Robin method of mixing of two lists in python在python中混合两个列表的循环方法
【发布时间】:2014-01-30 12:02:01
【问题描述】:

如果输入是

round_robin(range(5), "hello")

我需要输出为

[0, 'h', 1, 'e', 2, 'l', 3, 'l', 4, 'o']

我试过了

def round_robin(*seqs):
list1=[]
length=len(seqs)
list1= cycle(iter(items).__name__ for items in seqs)
while length:
    try:
        for x in list1:
            yield x
    except StopIteration:
        length -= 1

pass

但它给出了错误

AttributeError: 'listiterator' object has no attribute '__name__'

如何修改代码以获得想要的输出?

【问题讨论】:

标签: python python-2.7


【解决方案1】:

您可以使用zip 函数,然后使用列表理解将结果展平,就像这样

def round_robin(first, second):
    return[item for items in zip(first, second) for item in items]
print round_robin(range(5), "hello")

输出

[0, 'h', 1, 'e', 2, 'l', 3, 'l', 4, 'o']

zip 函数将两个可迭代对象的值分组,如下所示

print zip(range(5), "hello") # [(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')]

我们取出每一个元组并通过列表理解将其展平。

但正如@Ashwini Chaudhary 建议的那样,使用roundrobin receipe from the docs

from itertools import cycle
from itertools import 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))

print list(roundrobin(range(5), "hello"))

【讨论】:

  • 如果序列长度不等怎么办?
  • @thefourtheye 我正在制作一个每次都接受可变参数的函数。怎么办???
  • @AshwiniChaudhary 在这种情况下,zip 在第一个序列到达其末尾后终止。您可以使用itertools.zip_longest 填充None(或任何其他值)。
  • @JonasWielicki 我们不会在None(或任何其他值)中填充roundrobin,在这种情况下我们需要下一个可迭代的项目。
【解决方案2】:

您可以在此处找到一系列迭代配方:http://docs.python.org/2.7/library/itertools.html#recipes

from itertools import islice, cycle


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


print list(roundrobin(range(5), "hello"))

编辑:Python 3

https://docs.python.org/3/library/itertools.html#itertools-recipes

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    num_active = len(iterables)
    nexts = cycle(iter(it).__next__ for it in iterables)
    while num_active:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            num_active -= 1
            nexts = cycle(islice(nexts, num_active))

print list(roundrobin(range(5), "hello"))

【讨论】:

  • 它不适用于 round_robin([1, 2], "a", (5, 6, 7), [4])
  • @riteshbhat 我得到:[1, 'a', 5, 4, 2, 6, 7]。你运行的是哪个版本的python?
  • python 2.7.6 这是我的 o/p [1, 'a', 5, 4, 2, 6, ]
  • 我使用 python 2.7.5 但你的 o/p 很奇怪。你确定你复制了这段代码?
  • 哦,是的,你的代码完美运行,我犯了小错误。谢谢:)
【解决方案3】:

您可以利用itertools.chain(解开元组)和itertools.izip(转置元素以创建交错模式)来创建结果

>>> from itertools import izip, chain
>>> list(chain.from_iterable(izip(range(5), "hello")))
[0, 'h', 1, 'e', 2, 'l', 3, 'l', 4, 'o']

如果字符串长度不等,请使用 izip_longest 和填充值(最好是空字符串)

【讨论】:

    【解决方案4】:

    Python 2Python 3 的两个 itertools roundrobin 配方的混合如下所示:

    from itertools import islice, cycle
    
    def roundrobin(*iterables):
        "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
        # Recipe credited to George Sakkis
        num_active = len(iterables)
        try:
            iter([]).__next__  # test attribute
            nexts = cycle(iter(it).__next__ for it in iterables)
        except AttributeError:  # Python 2 behavior
            nexts = cycle(iter(it).next for it in iterables)
        while num_active:
            try:
                for next in nexts:
                    yield next()
            except StopIteration:
                # Remove the iterator we just exhausted from the cycle.
                num_active -= 1
                nexts = cycle(islice(nexts, num_active))
    
    print(list(roundrobin(range(5), "hello")))
    

    【讨论】:

      【解决方案5】:

      list(roundrobin('ABC', 'D', 'EF'))

      输出: ['A', 'D', 'E', 'B', 'F', 'C']

      def roundrobin(*iterables):
          sentinel = object()
          from itertools import chain
          try:
              from itertools import izip_longest as zip_longest
          except:
              from itertools import zip_longest 
          return (x for x in chain(*zip_longest(fillvalue=sentinel, *iterables)) if x is not sentinel)  
      

      【讨论】:

        【解决方案6】:

        对于寻找 Python 3 的任何人,请使用此

        def roundrobin(*iterables):
            "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
            # Recipe credited to George Sakkis
            num_active = len(iterables)
            nexts = cycle(iter(it).__next__ for it in iterables)
            while num_active:
                try:
                    for next in nexts:
                        yield next()
                except StopIteration:
                    # Remove the iterator we just exhausted from the cycle.
                    num_active -= 1
                    nexts = cycle(islice(nexts, num_active))
        

        不同之处在于 Python 3 的迭代器有 __next__() 而不是 next()https://docs.python.org/3/library/itertools.html#recipes

        【讨论】:

          【解决方案7】:

          从 itertools 导入周期

          A = [[1,2,3],[4,5,6],[7]]

          B = [[8],[9,10,11],[12,13]]

          对于 A 中的 p:

          max1 = len(p) if  max1 <len(p) else max1
          

          对于 B 中的 p:

          max1 = len(p) if  max1 <len(p) else max1
          

          i = len(A)

          j = 0

          C = []

          list_num = cycle(k for k in range(i))

          对于 list_num 中的 x:

          j += 1
          
          if j == i*3:
          
              break
          
          
          if A[x]:
          
              C.append(A[x].pop(0))
          
          if B[x]:
          
              C.append(B[x].pop(0)) 
          

          输出=====> [1, 8, 4, 9, 7, 12, 2, 5, 10, 13, 3, 6, 11]

          【讨论】:

          • 请解释为什么您的答案应该提供比已发布到此问题的其他答案更好的信息。如果您仍然确信它确实如此,请编辑您的答案并修复代码块格式。
          猜你喜欢
          • 2012-11-04
          • 2013-03-31
          • 2018-10-28
          • 2019-04-27
          • 1970-01-01
          • 2016-03-12
          • 1970-01-01
          • 1970-01-01
          • 2019-04-24
          相关资源
          最近更新 更多