根据您的问题设置,似乎没有替代方案可以遍历输入的字典列表。但是,这里有一个可以应用的多进程技巧。
以下是您的输入:
dict_a = {'1': "U", '2': "D", '3': "D", '4': "U", '5': "U", '6': "U"}
dict_b = {'1': "U", '2': "U", '3': "D", '4': "D", '5': "U", '6': "D"}
dict_c = {'1': "U", '2': "U", '3': "U", '4': "D", '5': "U", '6': "D"}
dict_d = {'1': "D", '2': "U", '3': "U", '4': "U", '5': "D", '6': "D"}
other_dicts = [dict_b, dict_c, dict_d]
我已经将@gary_fixler的地图技术包含为similarity1
,除此之外还有similarity2
函数,我将用它来进行循环技术。
def similarity1(a):
def _(b):
shared_value = set(a.items()) & set(b.items())
dict_length = len(a)
score_of_similarity = len(shared_value)
return score_of_similarity / dict_length
return _
def similarity2(c):
a, b = c
shared_value = set(a.items()) & set(b.items())
dict_length = len(a)
score_of_similarity = len(shared_value)
return score_of_similarity / dict_length
我们在这里评估3种技术:
(1)@gary_fixler的地图
(2)对字典列表进行简单循环
(3)对字典列表进行多进程处理
以下是执行语句:
print(list(map(similarity1(dict_a), other_dicts)))
print([similarity2((dict_a, dict_v)) for dict_v in other_dicts])
max_processes = int(multiprocessing.cpu_count()/2-1)
pool = multiprocessing.Pool(processes=max_processes)
print([x for x in pool.map(similarity2, zip(itertools.repeat(dict_a), other_dicts))])
你会发现所有三种技术都产生相同的结果:
[0.5, 0.3333333333333333, 0.16666666666666666]
[0.5, 0.3333333333333333, 0.16666666666666666]
[0.5, 0.3333333333333333, 0.16666666666666666]
请注意,对于多进程处理,您拥有
multiprocessing.cpu_count()/2
个核心(每个核心都具有超线程)。假设您的系统上没有其他运行程序,并且您的程序没有 I/O 或同步需求(这是我们问题的情况),则通常使用
multiprocessing.cpu_count()/2-1
个进程可以获得最佳性能,
-1
是为了父进程。
现在,来计时这三种技术:
print(timeit.timeit("list(map(similarity1(dict_a), other_dicts))",
setup="from __main__ import similarity1, dict_a, other_dicts",
number=10000))
print(timeit.timeit("[similarity2((dict_a, dict_v)) for dict_v in other_dicts]",
setup="from __main__ import similarity2, dict_a, other_dicts",
number=10000))
print(timeit.timeit("[x for x in pool.map(similarity2, zip(itertools.repeat(dict_a), other_dicts))]",
setup="from __main__ import similarity2, dict_a, other_dicts, pool",
number=10000))
这在我的笔记本电脑上产生了以下结果:
0.07092539698351175
0.06757041101809591
1.6528456939850003
您可以看到基本循环技术表现最佳。由于创建进程和传递数据的开销,多进程比其他两种技术明显差。这并不意味着在此处 multiprocessing 无用。相反地,请看更大数量的输入字典的结果:
for _ in range(7):
other_dicts.extend(other_dicts)
这将字典列表扩展到384个项目。以下是此输入的计时结果:
7.934810006991029
8.184540337068029
7.466550623998046
对于任何较大的输入字典集,多进程技术成为最优选择。
dict.items()
已经可以使用&
和其他集合运算符了。它不是一个列表,而是一个字典项的视图,类似于集合对象。 - juanpa.arrivillaga