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))
这里cycle
和islice
是itertools
(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的主要内容,如果未能解决你的问题,请参考以下文章