我有以下两个清单:
list_of_dicts = [
{'book': 1, 'title': 'novice'},
{'book': 2, 'title': 'novice'},
{'book': 3, 'title': 'novice'},
]
names = ['Johnny', 'Mike']
我想创建一个字典列表,表示这两个列表中每个列表的组合,如下所示:
data = [
{'book': 1, 'title': 'novice', name='Johnny'},
{'book': 1, 'title': 'novice', name='Mike'},
{'book': 2, 'title': 'novice', name='Johnny'},
{'book': 2, 'title': 'novice', name='Mike'},
{'book': 3, 'title': 'novice', name='Johnny'},
{'book': 3, 'title': 'novice', name='Mike'},
]
这是我到目前为止所做的,但应该有更好的方法:
data = []
for d in list_of_dicts:
for name in names:
new_d = d.copy()
new_d['name'] = name
data.append(new_d)
我问的原因是出于优化原因:在某些情况下,我的用例中的前两个列表可能很大。
答案 0 :(得分:4)
我们无法大幅提升它(在我们构造具有不同时间复杂度的算法的意义上),因为当前算法已经在输出字典的数量中运行,并且您无法构造 k <的列表/ em>元素小于 O(k)。
然而,我们可以使用例如列表理解和更有效的字典构造来提升性能:
Offers
如果我们将其与原始实现进行比较,我们会得到以下基准:
[{**d, 'name': name} for d in list_of_dicts for name in names]
基准计划:
old: 1.611422804009635
new: 1.3899883680278435 (-14%)
通常在处理大输入时,最好使用生成器,因为这意味着我们从不构造完整的元素列表,但只在需要时计算下一个元素。优点是双重的:如果我们之前切断迭代生成器,我们不会浪费周期来计算从未使用的字典,而且我们节省了内存,因为如果不再使用旧字典,它占用的内存可以重复使用。缺点是如果枚举了所有元素,则会产生一些使用生成器协议而浪费的开销。我们可以使用圆括号>>> def g():
... data = []
... for d in list_of_dicts:
... for name in names:
... new_d = d.copy()
... new_d['name'] = name
... data.append(new_d)
... return data
...
>>> def h():
... return [{**d, 'name': name} for d in list_of_dicts for name in names]
...
>>> timeit.timeit(g)
1.611422804009635
>>> timeit.timeit(h)
1.3899883680278435
代替方括号()
轻松将列表理解转换为生成器:
[]
如果每个字典都包含相同的键,我们也可以使用pandas。我们可以构造两个数据帧然后加入它们,例如:
({**d, 'name': name} for d in list_of_dicts for name in names)
对于小型数据集,Pandas的工作速度通常较慢,但如果这些数据集较大,通常会带来显着的加速。