我正在尝试优化一个嵌套的 for 循环,该循环将数组中的一个元素与数组中的其余元素进行比较。
有两部分,第一部分例如,一个数组有3个元素,每个元素是一个字典:
[{"someKey_1":"a"}, {"someKey_1":"b"}, {"somekey_1":"a"}]
第一次迭代(第一个元素与第二个元素比较):
测试两个元素的“someKey”键,因为a != b,所以我们什么都不做
第 2 次迭代(第 1 个元素与第 3 个元素比较):
测试两个元素的“someKey”键,因为a == a,我们做一些逻辑
代码:
for idx, val in enumerate(set_of_pk_values):
for idx_2, val_2 in enumerate(set_of_pk_values):
if (val['someKey'] == val_2['someKey'] and idx != idx_2):
#Some Logic
第二部分与前面的示例非常相似(列表中有 3 个项目),在同一个字典中,我们有一个与键关联的数组(现在数组的每个元素中有一个包含两个键的字典) ,比方说:
[{"someKey_1":[b,f]}{"someKey_2":a},
{"someKey_1":[e,f]}{"someKey_2":b},
{"somekey_1":[h,k]}{"someKey_2":c}]
第一次迭代(第一个元素与第二个元素比较):
使用键:someKey_1 遍历数组
b==b(第二个元素的 someKey_2),然后做一些逻辑
f!=b(第二个元素的 someKey_2),没有逻辑完成
第二次迭代(第一个元素与第三个元素比较):
使用键:someKey_1 遍历数组
b==c(第 3 个元素的 someKey_2),然后做一些逻辑
f!=c(第3个元素的someKey_2),没有做逻辑
代码:
for idx, val in enumerate(set_of_pk_values):
for idx_2, val_2 in enumerate(set_of_pk_values):
for pred in val['someKey_1']:
if(val_2['someKey_2'] == pred):
#Some Logic
目前第一个嵌套循环的运行时间:21 秒,第二个嵌套循环大约 19 秒。与其他流程相比,1-2 秒不等,这部分显然是一个瓶颈。
任何人都可以指出如何优化这段简单但极其耗时的代码的正确方向吗?
请您参考如下方法:
首先,我认为这应该发布在 CodeReview 上,而不是 StackOverflow。
StackOverflow 用于获取无法运行的代码的帮助。
CodeReview 是为了获得有关有效代码的帮助,但您想让它变得更好。
其次,这里有一些优化建议:
- 不要在循环内
enumerate()。 - 在第一种情况下使用切片以避免无意义的比较。
以下是我将如何重写您的第一个场景:
# Check if two dictionary with the key 'predecessor' are the same,
# and they are NOT the same index (otherwise it would be comparing themselves)
# set_of_pk_values is an array of dictionaries.
for idx, val in enumerate(set_of_pk_values):
for val_2 in set_of_pk_values[idx+1:]: # Note the slice and lack of enumerate
if (val['predecessor'] == val_2['predecessor']): # Don't waste time checking indexes
# Do Something Here, also we don't want to compare itself, because it will be true
代替for\if,使用if in:
for idx, val in enumerate(set_of_pk_values):
if val in set_of_pk_values[idx+1:]:
# Do Something Here, also we don't want to compare itself, because it will be true.
如果你真的想枚举,因为你只是想要多次相同的枚举,我会在循环外做一次并将它存储在一个变量中,然后循环它。这就是我的意思:
我错了,下面不起作用,请看评论。
# Doesn't work, see comments.
# from itertools import islice
# whatIEnumerate = enumerate(set_of_pk_values)
# for idx, val in whatIEnumerate:
# for idx_2, val_2 in islice(whatIEnumerate, idx+1, None):
# ...
