如何解决在某些条件下迭代集合的最有效方法是什么?
我有一个模拟设置,其中有一组元组。每个元组都包含我的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[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种条件过滤出元组?
如果需要,一些额外的信息:
- 我的仓库是一个1和0的3D numpy数组
- 随着整个模拟过程中这些值的变化,元组的集合将更新为0和1s的位置。
- 列表理解中的第三个条件使我获得了足够接近的结果,但是我对比较数据片段的理解并不十分自信。
谢谢您的帮助!
解决方法
这是部分解决方案,可以使速度适度提高。
它仍然使用列表推导,但是在较小的“元组”范围内循环。 (迭代次数将大大减少)
我在双引号中提到“元组”,因为在此解决方案中,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步:
在列表理解中:
- 将所有
zeros
替换为filt_zeros
- 删除第一个条件
让我知道它与全面数据集的关系。
,最后,我的解决方案是更改findSpot算法。 reloc_findSpot()
不再创建所有可能位置的列表,然后选择一个。现在,它返回第一个符合我在zeros
集中的条件的元素。
对于1000次循环运行,这将我的运行时间从15秒减少到0.4秒(必须测试更多循环的效率,但这已经是一个很大的改进)。这是通过生产线实现的
relocSpot = next(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[2]] == warehouse[-(ASdepth-1-coords[0]):,coords[1],coords[2]]).all())
看来我的结果没有受到影响(我猜因为集合没有排序,所以匹配条件的第一个项目总是随机的)。 谢谢大家的帮助!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。