Python 我不知道';我不明白为什么for循环不起作用
我正在ubuntu 19.04上运行python 3.7.3,使用visual studio代码1.39.1。我有点神经过敏,所以请耐心点 我正在用Python进行计算和编程。作者给出了我在VSC中输入的这个例子,我99%确定,准确率很高,但它没有完成程序应该做的,即找到两个列表的交集:Python 我不知道';我不明白为什么for循环不起作用,python,Python,我正在ubuntu 19.04上运行python 3.7.3,使用visual studio代码1.39.1。我有点神经过敏,所以请耐心点 我正在用Python进行计算和编程。作者给出了我在VSC中输入的这个例子,我99%确定,准确率很高,但它没有完成程序应该做的,即找到两个列表的交集: def相交(L1、L2): tmp=[] 对于L1中的e1: 对于L2中的e2: 如果e1==e2: tmp.append(e1) 打破 结果=[] 对于tmp中的e: 如果e没有结果: 结果.追加(e) 返回
def相交(L1、L2):
tmp=[]
对于L1中的e1:
对于L2中的e2:
如果e1==e2:
tmp.append(e1)
打破
结果=[]
对于tmp中的e:
如果e没有结果:
结果.追加(e)
返回结果
S=[2,3]
T=[2,3,4]
相交(S,T)
输出是[2]
而不是[2,3]
,因此程序似乎没有通过S
运行,但我不知道为什么
提前感谢。Python使用缩进标记代码块(如函数或循环体)的开头和结尾:
for condition:
statement_in_loop()
statement_in_loop()
statement_outside_of_loop()
如果要缩进最后一行,它将位于循环内部。有些语言使用大括号来标记循环体,Python则没有
复制/粘贴代码时要特别小心。通常,编辑器会尝试帮助您修复缩进,并最终更改逻辑
您的代码似乎过度缩进了最终循环,这使得它运行了太多次
试试这个:
def intersect(L1,L2):
tmp = []
for e1 in L1:
for e2 in L2:
if e1 == e2:
tmp.append(e1)
break
result = []
for e in tmp:
if e not in result:
result.append(e)
return result
S = [2,3]
T = [2,3,4]
intersect(S,T)
现在Adam已经给了你一个有效的解决方案,关于你的算法的效率也有一些要说的。请注意,这将超出您的问题范围 请注意,对于第一个列表中的每个元素,都会对第二个列表中的每个元素进行检查。这意味着,如果两个列表都有n个元素,则至少要进行n^2次比较。假设n变大了,比如100000,元素可能出现的大小范围足够大,那么您的算法能够处理这个问题吗?通常,如果可能的话,您希望尽量避免嵌套for循环。在这种情况下,它是: 让我们先导入一个工具来给我们随机数,因为我太懒了,无法手动生成100000个数字:
from random import randrange as rr
现在让我们设置一些高参数来测试算法:
list_length = 10000
random_space = 200000
让我们使用以下参数创建两个列表:
l1 = [rr(0,random_space,1) for i in range(list_length)]
l2 = [rr(0,random_space,1) for i in range(list_length)]
现在是正确缩进的算法,添加了一个变量checks
,告诉我们比较两个元素的大致次数:
def intersect(L1,L2):
tmp = []
checks = 0
for e1 in L1:
for e2 in L2:
checks += 1
if e1 == e2:
tmp.append(e1)
break
result = []
for e in tmp:
if e not in result:
result.append(e)
return result, checks
让我们把结果打印出来:
res, checks = intersect(l1, l2)
print(res)
print("Number of comparisons: "+str(checks))
现在运行代码。我想你会发现一切都是可行的,但这需要一点时间,而且比较的数量可能接近1亿!尝试将列表长度
从10000
更改为100000
,现在运行时代码是否会完成
现在让我们做一些修改。我们删除最后三行。然后,我们介绍了intersect函数的一个修改版本:
def intersect_v2(L1, L2):
dict = {}
checks = 0
for e1 in L1:
checks += 1
dict[e1] = 1
for e2 in L2:
checks += 1
if e2 in dict:
dict[e2] += 1
return [e for e in dict if dict[e] > 1], checks
res, checks = intersect_v2(l1, l2)
print(res)
print("Number of comparisons: "+str(checks))
请注意,我们在这里只对每个列表运行一次。这有多大区别
让我们测试一下。将列表长度更改回10000
。然后使用修改后的intersect函数将最后三行添加回:
def intersect_v2(L1, L2):
dict = {}
checks = 0
for e1 in L1:
checks += 1
dict[e1] = 1
for e2 in L2:
checks += 1
if e2 in dict:
dict[e2] += 1
return [e for e in dict if dict[e] > 1], checks
res, checks = intersect_v2(l1, l2)
print(res)
print("Number of comparisons: "+str(checks))
运行代码并查看。然后尝试将列表长度更改回100000
,然后再次运行。现在是否在合理的时间内完成
可能还有更有效的方法来做到这一点。但是摆脱嵌套for循环通常是一件大事。您需要修复缩进。在每一行中添加print语句,这将向您揭示python的行为,缩进非常重要。您复制了一些缩进的代码,它在loopok中运行,所以。您正在使用return
语句。在第一个非匹配对之后,您的函数将命中返回,并只返回结果。您必须允许两个循环结束,然后返回结果。@GSazheniuk:您能告诉我缩进需要修复吗?(或者,给我一个提示,如果你认为我最好自己去弄清楚这个问题)编辑:我明白你们在说什么,我想:它没有复制,因为我出于某种原因在VSC中键入了它。所有内容都缩进到def intersect行下方。代码现在工作正常,尽管它错过了显示结果的打印调用:print(intersect(S,T)