我正在尝试优化嵌套的for循环,将数组中的元素与数组中的其余元素进行比较。
有两个部分,第一部分,例如,Array有3个元素,每个元素都是一个字典:
[{"someKey_1":"a"}, {"someKey_1":"b"}, {"somekey_1":"a"}]
第一次迭代(第一元素与第二元素比较):
测试两个元素的"someKey“键,因为a != b,那么我们什么也不做
第2次迭代(第1元素与第3元素相比):
测试两个元素的"someKey“键,因为== 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 (第三元素的someKey_2),然后做一些逻辑
f!=c (第三元素的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秒不等,这部分显然是一个瓶颈。
有人能为我指出如何优化这段简单却非常耗时的代码的正确方向吗?
发布于 2015-03-16 17:34:17
第1部分的优化
原创
伙计,这太糟糕了:
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):
do_stuff()第一步
只需跳过您已经尝试过的元素的索引(==是可交换的):
for idx, val in enumerate(set_of_pk_values[:-1]):
for val_2 in set_of_pk_values[idx+1:]
if (val['someKey'] == val_2['someKey']):
do_stuff()步骤0.1
改名吧。太难看了。
for idx, first_dic in enumerate(set_of_pk_values[:-1]):
for second_dic in set_of_pk_values[idx+1:]
if (first_dic['someKey'] == second_dic['someKey']):
do_stuff()第二步
现在,每个循环迭代中的if都很麻烦。将其替换为过滤减少的列表:
hits = []
for idx, first_dic in enumerate(set_of_pk_values[:-1]):
hits += (first_dic['someKey'], filter(lambda dic: dic['someKey'] == first_dic['someKey'], set_of_pk_values[idx:1]) ) hits现在包含一个匹配元组的列表:hits[i] = ( mathing,first元素,,,具有idx > first element)的匹配列表。
第三步
查字典很贵。用operator.itemgetter替换它们
from operator import itemgetter
getter = itemgetter("someKey")
hits = []
for idx, first_dic in enumerate(set_of_pk_values[:-1]):
hits += (getter(first_dic), filter(lambda dic: getter(dic) == getter(first_dic), set_of_pk_values[idx:1]) )第四步
往后坐看看。for循环的迭代并不真正依赖于上一次迭代的状态。列表理解时间到了。
from operator import itemgetter
getter = itemgetter("someKey")
hits = [ ( getter(first_dic), filter(lambda dic: getter(dic) == getter(first_dic), set_of_pk_values[idx:-1]) ) for idx, first_dic in enumerate(set_of_pk_values[:-1])]发布于 2015-03-17 14:02:50
Python中的迭代要比C中的迭代慢,最好使用Python库在C中进行迭代。有趣的是没有人在这里提到itertools ..。
itertools.combinations在C中生成唯一的组合,然后返回组合的生成器:
import itertools
import operator
getter = operator.itemgetter('someKey_1')
for a, b in itertools.combinations(set_of_pk_values, 2):
if getter(a) == getter(b):
# logic?https://stackoverflow.com/questions/29044946
复制相似问题