首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python嵌套的循环数组比较-优化的可能性?

Python嵌套的循环数组比较-优化的可能性?
EN

Stack Overflow用户
提问于 2015-03-14 02:59:38
回答 2查看 2.4K关注 0票数 1

我正在尝试优化嵌套的for循环,将数组中的元素与数组中的其余元素进行比较。

有两个部分,第一部分,例如,Array有3个元素,每个元素都是一个字典:

[{"someKey_1":"a"}, {"someKey_1":"b"}, {"somekey_1":"a"}]

第一次迭代(第一元素与第二元素比较):

测试两个元素的"someKey“键,因为a != b,那么我们什么也不做

第2次迭代(第1元素与第3元素相比):

测试两个元素的"someKey“键,因为== a,我们做一些逻辑

守则:

代码语言:javascript
复制
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个项),在同一个字典中,我们有一个与键相关联的数组(现在,在数组的每个元素中有一个带有两个键的单一字典),比方说:

代码语言:javascript
复制
[{"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),没有逻辑

守则:

代码语言:javascript
复制
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秒不等,这部分显然是一个瓶颈。

有人能为我指出如何优化这段简单却非常耗时的代码的正确方向吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-16 17:34:17

第1部分的优化

原创

伙计,这太糟糕了:

代码语言:javascript
复制
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()

第一步

只需跳过您已经尝试过的元素的索引(==是可交换的):

代码语言:javascript
复制
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

改名吧。太难看了。

代码语言:javascript
复制
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都很麻烦。将其替换为过滤减少的列表:

代码语言:javascript
复制
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替换它们

代码语言:javascript
复制
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循环的迭代并不真正依赖于上一次迭代的状态。列表理解时间到了。

代码语言:javascript
复制
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])]
票数 4
EN

Stack Overflow用户

发布于 2015-03-17 14:02:50

Python中的迭代要比C中的迭代慢,最好使用Python库在C中进行迭代。有趣的是没有人在这里提到itertools ..。

itertools.combinations在C中生成唯一的组合,然后返回组合的生成器:

代码语言:javascript
复制
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?
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29044946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档