【问题标题】:Avoiding multiple nested for-loops in python避免python中的多个嵌套for循环
【发布时间】:2023-03-15 06:11:01
【问题描述】:

当一个嵌套的for循环的范围达到外部for循环的当前迭代时,如何避免多个嵌套的for循环?例如,考虑以下代码: 此程序从列表 arr 返回一个三元组,例如 arr[i] - arr[j] = arr[j] - arr[k] = di<j<k

d =3
arr = [1, 2, 4, 5, 7, 8, 10]
list1 = []

for biggest in range(0, len(arr)):
    for bigger in range(0, biggest):
        for big in range(0, bigger):
            if abs(arr[big] - arr[bigger]) == d and abs(arr[bigger] - arr[biggest]) == d:
                list1.append([arr[big], arr[bigger], arr[biggest]])
print(list1))

除了使用多个嵌套循环还有其他替代方法吗?

【问题讨论】:

  • 如果您的代码有效(似乎是这种情况),那么这里就是 OT,您想在 codereview 上重新发布。否则请具体说明问题所在。
  • 我认为这个问题在这里和代码审查无关,因为他正在寻找代码中的一项特定改进,而不是对所有方面的普遍忽视。

标签: python for-loop nested-loops


【解决方案1】:

您可以将三个循环替换为:

from itertools import combinations

for big, bigger, biggest in combinations(range(0, len(arr)), 3):

您可以将所有代码替换为:

print([t for t in combinations(arr, 3)
       if t[2] - t[1] == t[1] - t[0] == d])

【讨论】:

    【解决方案2】:

    您可以使用the combinations function from itertools。您的代码将变为:

    from itertools import combinations
    
    d = 3
    arr = [1, 2, 4, 5, 7, 8, 10]
    list1 = []
    for big, bigger, biggest in combinations(arr, 3):
        if abs(big - bigger) == d and abs(bigger - biggest) == d:
            list1.append([big, bigger, biggest])
    
    print(list1)
    

    它提供与您的代码相同的打印输出(在您删除最后一行多余的右括号之后):

    [[1, 4, 7], [2, 5, 8], [4, 7, 10]]
    

    请注意,我将变量 bigbiggerbiggest 的含义更改为数组值而不是它们的索引。使用值并避免使用索引更 Python 且更易于理解。

    您也可以在列表理解中执行此操作,以获得稍微不同的外观,避免临时列表,并可能提高速度。

    from itertools import combinations
    
    d = 3
    arr = [1, 2, 4, 5, 7, 8, 10]
    print([[big, bigger, biggest]
            for big, bigger, biggest in combinations(arr, 3)
            if abs(big - bigger) == d and abs(bigger - biggest) == d
        ])
    

    【讨论】:

    • 谢谢!但它比问题中的代码快吗?
    • @AkshayMurali:我用 return 语句替换了打印行以改​​进我的速度测试,我的两个例程都比你的快,我的第一个例程比我的第二个例程稍快。您的代码时间为 21.2 µs,我的第一个代码为 8.6 µs,第二个代码为 8.75 µs。所以列表推导并不比循环快,而且确实稍微慢了一点。
    【解决方案3】:

    虽然以前的答案是 pythonic, 如果你关心搜索算法的实现,你可以通过执行二分搜索算法在j+1和@的长度之间的空间中找到k,将算法的复杂度从O(N^3)降低到O(N^2logN) 987654325@满足d - abs(lst[j] - lst[k]) == 0

    d = 3
    lst = [1, 2, 4, 5, 7, 8, 10]
    
    
    def bsearch(lst, left, right, j):
        while left < right:
            k = (left + right) // 2
    
            diff = d - abs(lst[j] - lst[k])
    
            if diff == 0:
                return k
            if diff > 0:
                left = k + 1
            else:
                right = k
    
        return None
    
    
    l, result = len(lst), []
    for i in range(l):
        for j in range(i + 1, l):
            diff = d - abs(lst[i] - lst[j])
    
            if diff != 0: continue
            k = bsearch(lst, j + 1, l, j)
    
            if not k: continue
            result.append((lst[i], lst[j], lst[k]))
    
    print(result)
    
    [(1, 4, 7), (2, 5, 8), (4, 7, 10)]
    

    【讨论】:

      【解决方案4】:

      我猜找到了更好的方法!避免嵌套循环。

      arr = [1,2,3,4,5,6,7,8,9]
      d = 3
      list1 = arr
      list2 = []
      for each in (0,len(list1)):
          if list1[each] + d in arr and list1[each] + 2*d in arr:
               list2.append([list1[each], list1[each]+d, list1[each]+2*d])
      print(list2)
      

      【讨论】:

        猜你喜欢
        • 2017-08-27
        • 2017-11-11
        • 1970-01-01
        • 2019-12-26
        • 2012-06-25
        • 1970-01-01
        • 2017-09-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多