首页 > 解决方案 > 在某些条件下迭代集合的最有效方法是什么?

问题描述

我有一个模拟设置,其中有一组元组。每个元组都包含我的 numpy 数组中特定位置的索引。

在某些时候,我必须遍历这组元组以应用 3 个条件来过滤掉索引,然后我选择一个随机元组。我的代码如下:

def fillASRS(arr, fillLevel):
    toFill = round(float(vol*(fillLevel/100)))
    shape = arr.shape
    arr_1D = arr.reshape(-1)
    inds = np.random.choice(arr_1D.size, toFill, replace = False)
    arr_1D[inds] = 1
    arr_3D = np.array(arr_1D.reshape(shape))
    arr_3D.astype(np.int8)
    return arr_3D

warehouse = np.zeros([ASdepth,ASheight,ASlength])
warehouse = warehouse.astype(np.int8)
fillASRS(warehouse, z)
zeros = set(map(tuple,np.argwhere(warehouse==0)))

这是在开始时执行的,创建了我的 3D numpy 数组并用 1 和 0 填充,并创建了数组为 0 的一组位置。

之后我的代码如下所示:

def reloc_findSpot(coords):
    new_arr=[ele for ele in zeros if ele[0]==coords[0] if 1 not in warehouse[:ele[0],ele[1],ele[2]] if (warehouse[-(ASdepth-1-ele[0]):,ele[1],ele[2]] == warehouse[-(ASdepth-1-coords[0]):,coords[1],coords[2]]).all]
    random_idx=np.random.randint(len(new_arr))
    relocSpot = new_arr[random_idx]
    return relocSpot

在这里,我应用三个条件遍历我的集合,然后从现有的剩余条件中选择一个随机元组。如您所见,此条件取决于坐标,每次调用此函数时,坐标都是不同的元组。

我的程序需要很长时间才能执行(我运行 1000-100000 次迭代,具体取决于测试),当我分析它时,它告诉我我的大部分执行时间都花在了这个列表理解上,如下所示:

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.038    0.038   10.004   10.004 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\Simulation_Test.py:247(start)
      526    0.009    0.000    9.662    0.018 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\Simulation_Test.py:232(relocation)
      526    0.003    0.000    9.652    0.018 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\Simulation_Test.py:374(reloc_findSpot)
      526    9.643    0.018    9.643    0.018 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\Simulation_Test.py:375(<listcomp>)
      500    0.013    0.000    5.330    0.011 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\Simulation_Test.py:140(retrieval_Iteration)
      500    0.012    0.000    4.627    0.009 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\Simulation_Test.py:108(storage_Iteration)
     1000    0.051    0.000    0.269    0.000 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\Simulation_Test.py:363(rnd_findSpot)
     1000    0.187    0.000    0.204    0.000 C:\Users\Eduardo\AppData\Local\Programs\Python\Python38-32\lib\random.py:315(sample)

我的理解是列表理解基本上是在执行一个 for 循环,所以我认为把它变成一个 for 循环是没有用的。我的问题是,有没有办法更有效地遍历一个集合,并根据 3 个条件过滤掉元组?

如果需要一些额外的信息:

谢谢您的帮助!

标签: pythonoptimizationsetconditional-statementslist-comprehension

解决方案


这是一个部分解决方案,它将适度提高速度。

它仍然使用列表推导,但循环的“元组”范围要小得多。(迭代次数会少得多)

我在双引号中提到“元组”,因为在这个解决方案中,zeros不再是set对象tuple。相反,是一些大型zeros的二维numpy形状数组。(N,3)N

细节:

第 1 步(共 3 步):

将此行替换为zeros = set(map(tuple,np.argwhere(warehouse==0)))

zeros = np.argwhere(warehouse==0)

第 2 步(共 3 步):

reloc_findSpot(),在列表理解之前引入这一行:

filt_zeros = zeros[zeros[:,0] == coords[0]]

第 3 步(共 3 步):

在列表理解中:

  1. 全部替换zerosfilt_zeros
  2. 删除第一个条件

让我知道它与您的全尺寸数据集的关系。


推荐阅读