Python 在某些条件下迭代集合最有效的方法是什么?

Python 在某些条件下迭代集合最有效的方法是什么?,python,optimization,set,conditional-statements,list-comprehension,Python,Optimization,Set,Conditional Statements,List Comprehension,我有一个模拟装置,其中有一组元组。每个元组包含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

我有一个模拟装置,其中有一组元组。每个元组包含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
在这里,我应用这三个条件遍历我的集合,然后从现有的剩余元组中选择一个随机元组。如您所见,这个条件依赖于coords,每次调用这个函数时,coords都是一个不同的元组

我的程序需要很长的时间来执行(我根据测试运行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)

订购人:累计时间
ncalls tottime percall cumtime percall文件名:lineno(函数)
1 0.038 0.038 10.004 10.004 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\SIMULATION\u Test.py:247(开始)
526 0.009 0.000 9.662 0.018 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\SIMULATION\u Test.py:232(重新定位)
526 0.003 0.000 9.652 0.018 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\SIMULATION\u Test.py:374(reloc\u findSpot)
526 9.643 0.018 9.643 0.018 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\SIMULATION\u Test.py:375()
500 0.013 0.000 5.330 0.011 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\SIMULATION\u Test.py:140(检索\u迭代)
500 0.012 0.000 4.627 0.009 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\SIMULATION\u Test.py:108(存储迭代)
1000 0.051 0.000 0.269 0.000 c:\Users\Eduardo\Desktop\Thesis Docs\SIMULATION\SIMULATION\u Test.py:363(rnd\u findSpot)
1000 0.187 0.000 0.204 0.000 C:\Users\Eduardo\AppData\Local\Programs\Python\Python38-32\lib\random.py:315(示例)
我的理解是列表理解基本上是执行for循环,所以我认为将其转换为for循环是无用的。 我的问题是,有没有一种方法可以更有效地遍历集合,并根据3个条件过滤出元组

如果需要,请提供一些额外信息:

  • 我的仓库是一个带有1和0的3D numpy阵列
  • 随着0和1的位置在整个模拟过程中的变化,元组集将随着这些值的变化而更新
  • 列表理解中的第三个条件给了我足够接近的结果,但我对比较数据片段的理解不是很有信心

谢谢你的帮助

这是一个局部解决方案,可以适度提高速度

它仍然使用列表理解,但在更小的“元组”范围内循环。(迭代次数将少得多)

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

详细信息: 第1步,共3步:

将行
zeros=set(map(tuple,np.argwhere(warehouse==0))
替换为以下内容:

zeros = np.argwhere(warehouse==0)
第2步,共3步:

reloc\u findSpot()
中,在列表中引入此行之前:

filt_zeros = zeros[zeros[:,0] == coords[0]]
第3步,共3步:

在列表中:

  • 将所有
    替换为
    过滤零
  • 删除第一个条件

  • 让我知道它与您的全尺寸数据集的配合情况。

    这是一个局部解决方案,可以适度提高速度

    它仍然使用列表理解,但在更小的“元组”范围内循环。(迭代次数将少得多)

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

    详细信息: 第1步,共3步:

    将行
    zeros=set(map(tuple,np.argwhere(warehouse==0))
    替换为以下内容:

    zeros = np.argwhere(warehouse==0)
    
    第2步,共3步:

    reloc\u findSpot()
    中,在列表中引入此行之前:

    filt_zeros = zeros[zeros[:,0] == coords[0]]
    
    第3步,共3步:

    在列表中:

  • 将所有
    替换为
    过滤零
  • 删除第一个条件

  • 让我知道它如何与您的全尺寸数据集配合。

    因此,最终我的解决方案是更改我的findSpot算法
    reloc_findSpot()
    不再创建所有可能位置的列表,然后选择一个。现在,它返回与
    zeros
    集中的条件匹配的第一个元素

    这将我的运行时间从15秒减少到了0.4秒,可以运行1000个循环(需要测试更多循环的效率,但这已经是一个巨大的改进)。这是通过生产线实现的
    relocSpot=next(如果ele[0]==coords[0]如果1不在仓库[:ele[0],ele[1],ele[2]]如果(仓库[-(ASdepth-1-ele[0]):,ele[1],ele[2]==warehouse[-(ASdepth-1-coords[0]),coords[1],coords[2]])。all()

    我的结果似乎没有受到影响(我想因为集合没有排序,所以第一个匹配条件的项目总是随机的)。
    谢谢大家的帮助

    所以最后我的解决方案是改变我的findSpot算法
    reloc_findSpot()
    不再创建所有可能位置的列表,然后选择一个。它现在返回冷杉