python:从其他两个列表

时间:2018-02-14 20:49:46

标签: python

我有以下两个清单:

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)

我问的原因是出于优化原因:在某些情况下,我的用例中的前两个列表可能很大。

1 个答案:

答案 0 :(得分:4)

关于时间复杂性的说明

我们无法大幅提升它(在我们构造具有不同时间复杂度的算法的意义上),因为当前算法已经在输出字典的数量中运行,并且您无法构造 k <的列表/ em>元素小于 O(k)

使用 vanilla Python

进行提升

然而,我们可以使用例如列表理解和更有效的字典构造来提升性能:

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进行提升

如果每个字典都包含相同的键,我们也可以使用pandas。我们可以构造两个数据帧然后加入它们,例如:

({**d, 'name': name} for d in list_of_dicts for name in names)

对于小型数据集,Pandas的工作速度通常较慢,但如果这些数据集较大,通常会带来显着的加速。