python将不同列表的结果添加到单个列表中

时间:2015-10-23 10:51:58

标签: python list

我需要编写一个函数zipper(l1,l2,l3),它接受三个任意长度的列表,包含任意类型的元素。

该函数返回一个列表,其中包含以下列方式排序的这三个列表中的所有元素:列表1的元素1,列表2的元素1,列表3的元素1,列表1的元素2,列表2的元素2等等。当元素用完时,列表停止对最终列表做出贡献。

我尝试过使用此代码:

def zipper(l1,l2,l3):
    results = []
    length_1 = len(l1) - 1
    length_2 = len(l2) - 1
    length_3 = len(l3) - 1
    g = True
    h = True
    t = True
    i = 0
    while(g and h and t):
        if(length_1 <= i and g):
            results.append(l1[i])
        if(length_2 <= i and h):
            results.append(l2[i])
        if(length_3 <= i and t):
            results.append(l3[i])
        if(i > length_1):
            g = False
        elif(i > length_2):
            h = False
        elif(i > length_3):
            t = False

        i += 1
    return results

l1 = [1, 2, 3, 4, 5, 6, 7]
l2 = ["a", "b", "c"]
l3 = [[1,2], [1,2,3], "test", 300]

print(zipper(l1, l2, l3))

在示例中,结果应为:

[1, 'a', [1, 2], 2, 'b', [1, 2, 3], 3, 'c', 'test', 4, 300, 5, 6, 7]

5 个答案:

答案 0 :(得分:3)

这是一种类似于使用zip_longestfilter的方法,除了它是手动完成的。当然,在实际代码中,最好使用标准库函数,但是自己实现这些功能可能是一个有趣的学习练习。

此代码将采用任意数量的列表或其他迭代。它从每个迭代创建一个无限的生成器。当iterable耗尽元素时,无限生成器会产生一个名为Done的标记对象。

我们只是循环遍历这些生成器的列表,将非Done元素添加到我们的最终result列表中,当所有生成器生成Done时停止。

class Done:
    pass

def forever(it):
    for i in iter(it):
        yield i
    while True:
        yield Done

def zipper(*iterables):
    gens = [forever(it) for it in iterables]
    result = []
    while True:
        a = [u for u in [next(g) for g in gens] if u is not Done]
        if a == []:
            break
        result.extend(a)
    return result

l1 = [1, 2, 3, 4, 5, 6, 7]
l2 = ["a", "b", "c"]
l3 = [[1,2], [1,2,3], "test", 300]

print(zipper(l1, l2, l3))

<强>输出

[1, 'a', [1, 2], 2, 'b', [1, 2, 3], 3, 'c', 'test', 4, 300, 5, 6, 7]

答案 1 :(得分:1)

使用.pop列表可以大大简化。 这将循环,而任何列表中仍有元素,如果列表仍有项目,它将弹出输入的第一个元素并将其附加到结果列表。

def zipper(l1, l2, l3):
    results = []
    while l1 or l2 or l3:
        if l1:
            results.append(l1.pop(0))
        if l2:
            results.append(l2.pop(0))
        if l3:
            results.append(l3.pop(0))

     return results

答案 2 :(得分:0)

您可以使用itertools.izip_longest:for python 2x

>>> import itertools
>>> filter(lambda x: x!=None, [y for x in itertools.izip_longest(l1,l2,l3) for y in x])
[1, 'a', [1, 2], 2, 'b', [1, 2, 3], 3, 'c', 'test', 4, 300, 5, 6, 7]

使用itertools.zip_longest:for python 3x

>>> list(filter(lambda x: x!=None, [y for x in itertools.zip_longest(l1,l2,l3) for y in x]))
[1, 'a', [1, 2], 2, 'b', [1, 2, 3], 3, 'c', 'test', 4, 300, 5, 6, 7]

答案 3 :(得分:0)

from itertools import izip_longest,chain
l1 = [1, 2, 3, 4, 5, 6, 7]
l2 = ["a", "b", "c"]
l3 = [[1,2], [1,2,3], "test", 300]
a =list(chain(*(filter(None, pair) for pair in izip_longest(l1,l2,l3))))
print(a)

答案 4 :(得分:0)

如果我理解正确的话,我会对您的代码进行一些编辑,它可以完成您想要的操作。

   def zipper(l1,l2,l3):
       results = []
       g, h, t = True, True, True
       i = 0
       while(g or h or t):
           if(len(l1) > i):
               results.append(l1[i])
           else:
               g=False
           if(len(l2) > i):
               results.append(l2[i])
           else:
               h=False
           if(len(l3) > i):
               results.append(l3[i])
           else:
               t=False

           i += 1
       return results

   l1 = [1, 2, 3, 4, 5, 6, 7]
   l2 = ["a", "b", "c"]
   l3 = [[1,2], [1,2,3], "test", 300]

   print(zipper(l1, l2, l3))

输出

    [1, 'a', [1, 2], 2, 'b', [1, 2, 3], 3, 'c', 'test', 4, 300, 5, 6, 7]