Python:如何使用 for 循环合并两个列表,如 zip

Posted

技术标签:

【中文标题】Python:如何使用 for 循环合并两个列表,如 zip【英文标题】:Python: How to merge two lists like a zip with for loop 【发布时间】:2019-12-11 14:04:11 【问题描述】:

我遇到了一个问题,我有一个函数,它接受两个整数列表并返回一个整数列表(新列表),两个整数列表压缩在一起。

例如:

list1 = [1,2,3]
list2 = [4,5,6]

应该给[1, 4, 2, 5, 3, 6]而不是[1, 2, 3, 4, 5, 6]

另一种情况是如果一个列表比另一个长,例如:

list1 = [1,2]
list2 = [4,5,6,9]

一旦较短的列表用完项目,较长的列表应该添加其剩余元素。例如:[1, 4, 2, 5, 6, 9]

我尝试使用条件语句来检查哪个列表更长,并使用 for 循环追加到应该返回的新列表。我尝试使用在较短列表期间循环的 for 循环,一旦 for 循环结束,它会将较长列表中的剩余元素添加到新列表中。此外,如果两个列表都是空的,我必须返回一个空的新列表。

代码:

def main():
    list1 = [1,2]
    list2 = [4,5,6,9]
    print(zip_lists(list1, list2))

def zip_lists(list1, list2):
    new_list = []

    if len(list1) > len(list2):
        last_num = list1[len(list1):]
        for num in range(0, len(list2)):
            new_list.append(list1[num])
            new_list.append(list2[num])
        new_list.append(last_num)
        return new_list

    elif len(list2) > len(list1):
        last_num = list2[len(list2):]
        for num in range(0, len(list1)):
            new_list.append(list1[num])
            new_list.append(list2[num])
        new_list.append(last_num)
        return new_list


    elif len(list1) and len(list2) == 0:
        return new_list


main()

但是,我有一个问题,我无法从较长的列表中添加剩余元素,而是返回带有空方括号的部分压缩列表。

测试用例:

list1 = [1,2]
list2 = [4,5,6,9]

应该是 [1, 4, 2, 5, 6, 9] 但我得到的是 [1, 4, 2, 5, []]。

我的代码是否显示了对这个问题的正确思考方式?

【问题讨论】:

elif len(list2) > len(list1)的情况下last_num应该是list2[len(list1):] ...和new_list+=last_num。在另一种情况下出现同样的错误。 【参考方案1】:
def zip_lists(list1, list2):
    n1=len(list1)
    n2=len(list2)
    k = []
    n = min(n1, n2)
    for i in range(n):
        k.append(list1[i])
        k.append(list2[i])

    if n1==n2:
        return k 
    if n1>n2:
        return k+list1[n:]
    else:
        return k+list2[n:]

测试:

list1 = [1,2]
list2 = [4,5,6,9]
zip_lists(list1, list2) 

输出:[1, 4, 2, 5, 6, 9]

【讨论】:

【参考方案2】:

您可以使用zip_longest 来执行此操作:

代码:

from itertools import zip_longest
def merge(l1, l2):
    for i in zip_longest(l1, l2):
        for j in i:
            if j is not None:
                yield j

测试代码:

list1 = [1, 2, 3]
list2 = [4, 5, 6]
ans1 = [1, 4, 2, 5, 3, 6]

list3 = [1, 2]
list4 = [4, 5, 6, 9]
ans2 = [1, 4, 2, 5, 6, 9]

assert list(merge(list1, list2)) == ans1
assert list(merge(list3, list4)) == ans2

【讨论】:

【参考方案3】:

itertools standard library 的 Python 文档中显示了这个的通用版本(即,对于任意数量的源迭代,可能具有不同的长度),在 "recipes" section 中命名为 roundrobin。复制到这里,并附上原始出处:

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

这里cycleisliceitertools(from itertools import cycle, islice)提供的功能;其余的是内置的。请注意,这是一个生成器,而不是普通函数;您将需要自己对其进行迭代(或直接从中创建一个列表,例如merged = list(roundrobin(list1, list2)))。


至于调试您对代码的尝试,让我们考虑list1 更长的情况(list2 更长的情况有并行问题;它们相等的情况工作正常,是吗? ):

    last_num = list1[len(list1):] # problem 1
    for num in range(0, len(list2)):
        new_list.append(list1[num])
        new_list.append(list2[num])
    new_list.append(last_num) # problem 2

问题 1:您想从 list1 中提取“多余”元素,您将其确定为超过某个特定点的所有元素。这只是一个错字或没有清楚地考虑它;您想使用 list2 的长度作为要分割的元素数;当然,使用list1 的长度从list1 中删除元素会删除所有内容。

问题 2:您有一个列表,您希望将其元素连接到另一个列表的末尾。 .append 将其参数视为单个新列表元素,即使它是一个列表;就像 Python 之禅所说的那样,special cases aren't special enough to break the rules(请记住,有时您可能想要这样做,毕竟)。相反,您正在寻找的方法是 .extend

【讨论】:

【参考方案4】:
import numpy as np
l=len(a) if len(a)<len(b) else len(b)
a=np.array(list1[:l])
b=np.array(list2[:l])
ab=np.vstack((a, b)).T.flatten()
res=list(ab)+list1[l:]+list2[l:]

【讨论】:

因为numpy是科学计算库,所以很难详细解释。 T 是矩阵转置。

以上是关于Python:如何使用 for 循环合并两个列表,如 zip的主要内容,如果未能解决你的问题,请参考以下文章

如何在列表理解python中构建两个for循环

python 如何在一个for循环中遍历两个列表

在python中如何将两个list合并成一个list,不用for语句

python两个列表进行合并

python如何合并两个列表?

如何在不使用for循环的情况下合并需要提前3个月的列上的两个数据框