代码之家  ›  专栏  ›  技术社区  ›  davidchambers

以一种交替的方式将两个列表结合起来?

  •  64
  • davidchambers  · 技术社区  · 14 年前

    我有两张单子, . 我想知道创建一个新列表的最python的方法,它的偶数索引值来自第一个列表,奇数索引值来自第二个列表。

    # example inputs
    list1 = ['f', 'o', 'o']
    list2 = ['hello', 'world']
    
    # desired output
    ['f', 'hello', 'o', 'world', 'o']
    

    list3 = []
    while True:
        try:
            list3.append(list1.pop(0))
            list3.append(list2.pop(0))
        except IndexError:
            break
    

    否则如何才能做到这一点?什么是最具霸道的方法?

    18 回复  |  直到 14 年前
        1
  •  126
  •   Duncan    14 年前

    这里有一种方法可以通过切片来实现:

    >>> list1 = ['f', 'o', 'o']
    >>> list2 = ['hello', 'world']
    >>> result = [None]*(len(list1)+len(list2))
    >>> result[::2] = list1
    >>> result[1::2] = list2
    >>> result
    ['f', 'hello', 'o', 'world', 'o']
    
        2
  •  52
  •   ruddra    4 年前

    这里面有一个食谱 itertools documentation :

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

    编辑:

    对于大于3的python版本:

    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))
    
        3
  •  31
  •   Mark Byers    14 年前

    这应该是你想要的:

    >>> iters = [iter(list1), iter(list2)]
    >>> print list(it.next() for it in itertools.cycle(iters))
    ['f', 'hello', 'o', 'world', 'o']
    
        4
  •  30
  •   Vamsi Nerella    10 年前
    import itertools
    print [x for x in itertools.chain.from_iterable(itertools.izip_longest(list1,list2)) if x]
    

    我认为这是最有毒瘾的方法。

        5
  •  20
  •   Zart    14 年前

    >>> sum(zip(l1, l2+[0]), ())[:-1]
    ('f', 'hello', 'o', 'world', 'o')
    

    使用itertools并假设列表不包含任何内容:

    >>> filter(None, sum(itertools.izip_longest(l1, l2), ()))
    ('f', 'hello', 'o', 'world', 'o')
    
        6
  •  13
  •   Community uzul    7 年前

    这里是 Duncan's solution

    list1 = ['f', 'o', 'o', 'b', 'a', 'r']
    list2 = ['hello', 'world']
    num = min(len(list1), len(list2))
    result = [None]*(num*2)
    result[::2] = list1[:num]
    result[1::2] = list2[:num]
    result.extend(list1[num:])
    result.extend(list2[num:])
    result
    

    这将输出:

    ['f', 'hello', 'o', 'world', 'o', 'b', 'a', 'r'] 
    
        7
  •  8
  •   Arco Bast    4 年前

    [x for y in zip(list1, list2) for x in y]
    

    由于第一个列表还有一个元素,您可以将其添加到后期:

    [x for y in zip(list1, list2) for x in y] + [list1[-1]]
    
        8
  •  6
  •   Jay    14 年前

    list3 = [ item for pair in zip(list1, list2 + [0]) for item in pair][:-1]

        9
  •  2
  •   killown    14 年前
    def combine(list1, list2):
        lst = []
        len1 = len(list1)
        len2 = len(list2)
    
        for index in range( max(len1, len2) ):
            if index+1 <= len1:
                lst += [list1[index]]
    
            if index+1 <= len2:
                lst += [list2[index]]
    
        return lst
    
        10
  •  2
  •   catpnced    12 年前

    这是基于卡洛斯·瓦林特的贡献

    A=["a","b","c","d"]
    B=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
    
    def cyclemix(xs, ys, n=1):
        for p in range(0,int((len(ys)+len(xs))/n)):
            for g in range(0,min(len(ys),n)):
                yield ys[0]
                ys.append(ys.pop(0))
            for g in range(0,min(len(xs),n)):
                yield xs[0]
                xs.append(xs.pop(0))
    
    print [x for x in cyclemix(A, B, 3)]
    

    这将按每组3个值交错列出A和B:

    ['a', 'b', 'c', 1, 2, 3, 'd', 'a', 'b', 4, 5, 6, 'c', 'd', 'a', 7, 8, 9, 'b', 'c', 'd', 10, 11, 12, 'a', 'b', 'c', 13, 14, 15]
    
        11
  •  2
  •   Allen Qin    6 年前

    可能有点晚了再买一条蟒蛇一行。当两个列表的大小相等或不相等时,这种方法就起作用了。值得一提的是,它将修改a和b。如果这是一个问题,您需要使用其他解决方案。

    a = ['f', 'o', 'o']
    b = ['hello', 'world']
    sum([[a.pop(0), b.pop(0)] for i in range(min(len(a), len(b)))],[])+a+b
    ['f', 'hello', 'o', 'world', 'o']
    
        12
  •  1
  •   Carlos Valiente    14 年前

    a = "hlowrd"
    b = "el ol"
    
    def func(xs, ys):
        ys = iter(ys)
        for x in xs:
            yield x
            yield ys.next()
    
    print [x for x in func(a, b)]
    
        13
  •  1
  •   chernevik    14 年前

    这是一个使用列表理解的单行程序,没有其他库:

    list3 = [sub[i] for i in range(len(list2)) for sub in [list1, list2]] + [list1[-1]]
    

    如果您允许通过副作用更改初始列表1,还有另一种方法:

    [list1.insert((i+1)*2-1, list2[i]) for i in range(len(list2))]
    
        14
  •  1
  •   GeneralCode    4 年前
    from itertools import chain
    list(chain(*zip('abc', 'def')))  # Note: this only works for lists of equal length
    ['a', 'd', 'b', 'e', 'c', 'f']
    
        15
  •  0
  •   jwp    14 年前

    在最短时间内停车:

    def interlace(*iters, next = next) -> collections.Iterable:
        """
        interlace(i1, i2, ..., in) -> (
            i1-0, i2-0, ..., in-0,
            i1-1, i2-1, ..., in-1,
            .
            .
            .
            i1-n, i2-n, ..., in-n,
        )
        """
        return map(next, cycle([iter(x) for x in iters]))
    

    当然,解析next/\uu next\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。

        16
  •  0
  •   spiderknight    11 年前

    list3 = [element for element in list(itertools.chain.from_iterable([val for val in itertools.izip_longest(list1, list2)])) if element != None]
    
        17
  •  0
  •   Community uzul    7 年前

    灵感来源于 answers to another question

    import itertools
    
    list(itertools.chain.from_iterable(itertools.izip_longest(list1, list2, fillvalue=object)))[:-1]
    
    [i for l in itertools.izip_longest(list1, list2, fillvalue=object) for i in l if i is not object]
    
    [item for sublist in map(None, list1, list2) for item in sublist][:-1]
    
        18
  •  0
  •   Nikolay Frick    5 年前

    努比呢?它也适用于字符串:

    import numpy as np
    
    np.array([[a,b] for a,b in zip([1,2,3],[2,3,4,5,6])]).ravel()
    

    结果:

    array([1, 2, 2, 3, 3, 4])
    
        19
  •  0
  •   godot    5 年前

    from itertools import zip_longest
    from functools import reduce
    
    reduce(lambda lst, zipped: [*lst, *zipped] if zipped[1] != None else [*lst, zipped[0]], zip_longest(list1, list2),[])
    
        20
  •  -1
  •   wheaties    14 年前

    我要做的很简单:

    chain.from_iterable( izip( list1, list2 ) )
    

    它将提供一个迭代器,而不需要创建任何额外的存储需求。

        21
  •  -2
  •   Tom Anderson    14 年前

    我年纪太大了,无法理解列表,所以:

    import operator
    list3 = reduce(operator.add, zip(list1, list2))