【问题标题】:Rephrasing nested for loops in Python改写 Python 中的嵌套 for 循环
【发布时间】:2021-06-27 13:05:14
【问题描述】:

以下代码有多个循环,我想减少它以优化时间复杂度。

for a in file1:
    if a[0] in [i[1] for i in file2]:
        for b in file2:
            if a[0] == b[1]:
                c.append(int(b[0]))
            continue
    else:
        # do stuff

我尝试了以下方法以提高效率。虽然,我找不到 if 语句的替代方法。

for a, b in zip(file1, file2):
    if a[0] in [i[1] for i in file2]:
        if a[0] == b[1]:
            c.append(int(b[0]))
        continue
    else:
        # do stuff

此外,两种操作的输出也不同。第一段代码确实显示了正确的结果。

【问题讨论】:

  • 第一个代码示例对file2 进行了两次迭代,这似乎很浪费。您不妨删除第一个 if 语句。
  • 请注意,'zip' 给了我们配对。令 a=[1,2,3], b = ['a', 'b', 'c'],然后 list(zip(a,b)) = [(1,'a'), (2, 'b'), (3,'c')]。如果您需要使用更少的循环来重写代码(但为什么?...),请尝试使用 itertools.product 而不是 zip。然后请注意,如果您的第一个“if”没有用,只会增加评估时间:您循环 file2 两次,首先确定是否有任何元素适合,然后再找到它。然后在第一个 sn-p 中“继续”什么都不做,它在循环的末尾。而且这段代码总是 O(n^2) 或更多,因为你需要遍历每对元素。

标签: python functional-programming itertools


【解决方案1】:

您的第二个解决方案实际上更慢。 zip 的想法(或者更确切地说,它应该像 itertools.product,zip 产生N 对)产生NxM 对,所以你的整个解决方案现在是O(NxMxM),而第一个应该是O(Nx2M)。我不确定您的 continue 声明是做什么的,这似乎毫无意义。

我的建议是预先计算您的一些值,并使用集合/字典。 [i[1] for i in file2] 在每个循环中都是一样的,所以把它去掉。

此外,由于您将 ba 按值对齐,因此我们创建一个反向查找字典。

# build reverse lookup dictionary
reverse = dict()
for b in file2:
    if not b[1] in reverse:
        reverse[b[1]] = [b]
    else:
        reverse[b[1]].append(b)

# check to see if a[0] matches any b[1], if it does append all matching b[0] to c
for a in file1:
    if a[0] in reverse:
        b_valid = reverse[a[0]]
        for b in b_valid:
            c.append(int(b[0]))
    else:
        # do stuff

这使它在O(N+M) 的范围内下降(考虑到字典创建时间和查找时间很差,可能会更糟)。

【讨论】:

    【解决方案2】:

    试试:

    next((x for x in file2 if a[0] == x[1]), None)
    

    这会给你合适的,如果不是None,你应该可以追加。

    【讨论】:

      猜你喜欢
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 2020-10-09
      • 2020-06-08
      • 2020-05-25
      相关资源
      最近更新 更多