python - Python中过滤的优化
问题描述
我需要can_clump
在 python 中的许多对象上运行一个复杂的函数。这需要很长时间才能运行,所以我正在尝试优化。
只有一些对象需要can_clump
在它们上面运行,所以我正在尝试过滤。
我目前拥有的解决方案在这里:
for clump1 in stored.clumps:
for clump2 in stored.clumps:
if clump1.classification = clump2.classification:
if clump1.can_clump(clump2):
#some code here
但我不确定我是否可以结合 if 语句 if an and 来简化它,或者这是否需要 python 到 python 来检查两者:
for clump1 in stored.clumps:
for clump2 in stored.clumps:
if clump1.classification = clump2.classification and clump1.can_clump(clump2):
#some code here
或者,在迭代之前过滤列表甚至可能更快:
for clump1 in stored.clumps:
for clump2 in filter(lambda x: x.classification == clump1.classification, stored.clumps):
if clump1.can_clump(clump2):
#some code here
我不确定哪个更快并且应该实施。
解决方案
首先,结合你的两个条件很容易:
for clump1 in stored.clumps:
for clump2 in stored.clumps:
if clump1.classification == clump2.classification and clump1.can_clump(clump2):
#some code here
做你想做的事,它会短路;如果第一次测试失败,can_clump
将不会被调用。
其次,作为一项规则,filter
当需要 alambda
来实现它时,它通常会比较慢;唯一一次看到有意义的节省是谓词本身是用 C 实现的内置函数。如果您已经需要调用现有的 Python 定义的函数,那么filter
通常没有好坏之分,因此使用它几乎没有什么坏处.
因此,对于您的情况,假设它classification
是内置类型(或 C 扩展实现的类型),您可能可以通过以下方式进行一些优化:
for clump1 in stored.clumps:
for clump2 in filter(clump1.can_clump, filter(clump1.classification.__eq__, stored.clumps)):
#some code here
也就是说,这都是微优化。即使它有效,我们谈论的可能是 10% 的加速,如果这是代码中最热门的部分,并且一切正常。通常,担心微优化是浪费时间。99% 的情况下,如果没有它,性能还是不错的,或者无论你是否这样做,性能都会慢得让人无法接受。
在这种情况下,您可能会从对块进行预分组中获得更多收益,减少O(n²)
嵌套迭代的工作,stored.clumps
这些工作至少可以完成O(n log n)
(with sorted
+ itertools.groupby
) 或O(n)
(with a multi-中的一些工作dict
,例如collections.defaultdict(list)
)。例如,按分类分组的预处理运行可以是:
# Imports at top of file
from collections import defaultdict
from itertools import product
# Code using them
clumps_by_classification = defaultdict(list)
for clump in stored.clumps:
clumps_by_classification[clump.classification].append(clump)
现在,您可以将子组与匹配的分类进行比较,而不是将每个簇与其他簇进行比较:
for classification, clumps in clumps_by_classification.items():
for clump1, clump2 in product(clumps, repeat=2):
if clump1.can_clump(clump2):
# some code here
根据团块排序是否重要,以及团块是否应该能够与自己结块,您可以通过替换product
另一个itertools
函数(如combinations
、combinations_with_replacement
或)来节省更多permutations
。
是的,理论上,该product(repeat=2)
步骤保留了工作O(n²)
,但现在是O(n²)
当n
是具有相同 的最大子群时classification
,而不是就整个丛集而言。
推荐阅读
- python - Python 字典和列表比较
- javascript - 对所有 javascript 类型使用 in 运算符
- c# - 对多个按钮属性进行分组
- android-studio - Android Studio 中终端的启动文件
- javascript - Promise 是如何构建的?
- javascript - 在图像缩略图中阅读更多信息
- go - 创建通用函数以从地图中提取值
- docker - 如何使用 docker(不是 vagrant 或 virtualbox)在 mac os High Sierra 上运行 kubernetes?
- python - 当值为“无”时如何使用理解来查找字典键?
- json - Spark数据框需要json文件作为一行中的一个对象?