Skip to main content
 首页 » 编程设计

python之遍历 Python 字典非常慢

2025年05月04日28sky-heaven

我正在尝试根据分配给用户的项目值来计算用户对之间的距离。但是,当两个用户没有任何交叉项目时,距离计算应该为空。我也只计算距离矩阵的下半部分(例如,UserA-UserB 等同于 UserB-UserA,所以只计算一个)。

所以我有下面这个有效的 Python 脚本,但是当我为它提供超过几百个用户时它真的开始出现问题。下面的示例脚本显示了输入结构,但我试图做数千个,而不仅仅是我在此处显示的四个。

行 s = {k:v for k,v in data.items() if k in (user1,user2)} 似乎增加了最多的开销

import math 
from decimal import * 
 
def has_matching_product(data,user1,user2): 
    c1=set(data[user1].keys()) 
    c2=[k for k in data[user2].keys()] 
    return any([x in c1 for x in c2]) 
 
def get_euclidean_dist(data,user1,user2): 
    #Tried subsetting to run quicker? 
    s = {k:v for k,v in data.items() if k in (user1,user2)} 
 
    #Ignore users with no overlapping items 
    if has_matching_product(s,user1,user2): 
        items=set() 
        for k,v in s.items(): 
            for ki in v.keys(): 
                items.add(ki) 
 
        rs=Decimal(0) 
        for i in items: 
            p1 = s.get(user1).get(i) 
            p2 = s.get(user2).get(i) 
            v1 = p1 or 0 
            v2 = p2 or 0 
 
            rs+= Decimal((v1-v2)**2) 
        return math.sqrt(rs) 
    else: 
        return None 
 
#User/Product/Value 
raw_data = { 
    'U1': { 
        'I1':5, 
        'I4':2 
    }, 
    'U2': { 
        'I1':1, 
        'I3':6 
    }, 
    'U3': { 
        'I3':11 
    }, 
    'U4': { 
        'I4':9 
    } 
} 
 
users = sorted(raw_data.keys()) 
l = len(users) 
 
data_out = set() 
#Compute lower half of a distance matrix (unique pairs only) 
for u1 in range(0,l-1): 
    for u2 in range(1+u1,l): 
        dist = get_euclidean_dist(raw_data,users[u1],users[u2]) 
        print('{x} | {y} | {d}'.format(x=users[u1],y=users[u2],d=dist)) #Sample output 

正确的输出应该是这样的:

U1 | U2 | 7.483314773547883 
U1 | U3 | None 
U1 | U4 | 8.602325267042627 
U2 | U3 | 5.0990195135927845 
U2 | U4 | None 
U3 | U4 | None 

请您参考如下方法:

问题是您每次都在遍历整本词典,只是为了找到您想要的两个项目。从表面上看,您正在提取 user,然后花费所有时间尝试在 data 中再次找到它们。 @Peter Wood 的建议会大有帮助——首先只抓取你想要的两个 user,但这有点像不见了森林——你不需要精简你的字典首先。将它们放在一起:

import itertools 
for kv1, kv2 in itertools.combinations(data.items(), 2): 
    ## calculate distance directly here