我不明白为什么for循环不起作用

时间:2019-10-16 20:42:51

标签: python

我正在使用Visual Studio代码1.39.1在ubuntu 19.04上运行python 3.7.3。我有点菜鸟,请耐心等待。

我正在使用Python进行计算和编程。作者给出了我输入VSC的这个示例,我对99%的准确率表示肯定,但是它没有执行程序应做的工作,即找到两个列表的交集:

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)

输出为[2]而不是[2,3],因此该程序似乎未通过S运行,但我不知道为什么。

谢谢。

2 个答案:

答案 0 :(得分:3)

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)

答案 1 :(得分:1)

现在,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亿!尝试将list_length10000更改为100000,当您现在运行代码时,代码是否还会完成?

现在让我们进行一些更改。我们删除最后三行。然后我们介绍交叉函数的修改版本:

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

请注意,我们在这里只浏览每个列表一次。这有多大的不同?

让我们测试一下。将list_length改回10000。然后使用修改后的intersect函数将最后三行添加回去:

res, checks = intersect_v2(l1, l2)
print(res)
print("Number of comparisons: "+str(checks))

运行代码,然后查看。然后尝试将list_length改回100000并再次运行。现在是否在合理的时间内完成?

也许有更有效的方法可以做到这一点。但是,摆脱嵌套的for循环通常很重要。