Python 正在使用另一个词典列表更新词典列表。有没有更快的办法?
我有一个字典列表,我需要用另一个字典列表中的信息更新它。我当前的解决方案(如下)是从第一个列表中选取每一本词典,并将其与第二个列表中的每一本词典进行比较。这是可行的,但有没有一种更快、更优雅的方法可以达到同样的效果Python 正在使用另一个词典列表更新词典列表。有没有更快的办法?,python,Python,我有一个字典列表,我需要用另一个字典列表中的信息更新它。我当前的解决方案(如下)是从第一个列表中选取每一本词典,并将其与第二个列表中的每一本词典进行比较。这是可行的,但有没有一种更快、更优雅的方法可以达到同样的效果 a = [ { "id": 1, "score":200 }, { "id": 2, "score":300 }, { "id":3, "score":400 } ] b = [ { "id": 1, "newscore":500 }, { "id": 2, "newscore":6
a = [ { "id": 1, "score":200 }, { "id": 2, "score":300 }, { "id":3, "score":400 } ]
b = [ { "id": 1, "newscore":500 }, { "id": 2, "newscore":600 } ]
# update a with data from b
for item in a:
for replacement in b:
if item["id"]==replacement["id"]:
item.update({"score": replacement["newscore"]})
使用第一个数组创建由
id
索引的字典。
使用id
循环第二个数组
for replacement in b:
v = lookup.get(replacement['id'], None)
if v is not None:
v['score'] = replacement['newscore']
这会将O(n^2)
问题转换为O(n)
问题。过程b不是执行len(a)*len(b)循环,而是更容易处理:
In [48]: replace = {d["id"]: {"score": d["newscore"]} for d in b}
In [49]: new_a = [{**d, **replace.get(d['id'], {})} for d in a]
In [50]: new_a
Out[50]: [{'id': 1, 'score': 500}, {'id': 2, 'score': 600}, {'id': 3, 'score': 400}]
请注意,
{**somedict}
语法需要Python的现代版本(>=3.5.)如果您愿意使用pandas
并且a、b是pandas数据帧,那么这里是一个单行程序
a.loc[a.id.isin(b.id), 'score'] = b.loc[b.id.isin(a.id), 'newscore']
将a,b转换为数据帧很简单,只需使用pd.DataFrame.from\u records
如果您可以将“newscore”更改为“score”,则可以使用另一种方法 下面是timeit的结果
In [10]: %timeit c = a.copy(); c.update(b)
702 µs ± 37.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
列表理解:
[i.update({"score": x["newscore"]}) for x in b for i in a if i['id']==x['id']]
print(a)
%timeit [i.update({"score": x["newscore"]}) for x in b for i in a if i['id']==x['id']]
输出:
[{'id': 1, 'score': 500}, {'id': 2, 'score': 600}, {'id': 3, 'score': 400}]
100000 loops, best of 3: 3.9 µs per loop
计时:
[i.update({"score": x["newscore"]}) for x in b for i in a if i['id']==x['id']]
print(a)
%timeit [i.update({"score": x["newscore"]}) for x in b for i in a if i['id']==x['id']]
输出:
[{'id': 1, 'score': 500}, {'id': 2, 'score': 600}, {'id': 3, 'score': 400}]
100000 loops, best of 3: 3.9 µs per loop
首先创建要更新的分数记录:
>>> new_d={d['id']:d for d in b}
>>> new_d
{1: {'id': 1, 'newscore': 500}, 2: {'id': 2, 'newscore': 600}}
然后在上迭代并按id更新:
for d in a:
if d['id'] in new_d:
d['score']=new_d[d['id']]['newscore']
>>> a
[{'id': 1, 'score': 500}, {'id': 2, 'score': 600}, {'id': 3, 'score': 400}]
更简单的是:
new_d={d['id']:d['newscore'] for d in b}
for d in a:
if d['id'] in new_d:
d['score']=new_d[d['id']]
您是否愿意使用像
pandas
这样的库?a
的第一个元素列表是否总是与b
中匹配的元素列表元素具有相同的索引?如果您有一个非常大的数据集并且需要这样做,考虑移动到一个更快的语言,如SWIFT或生锈或C。Python努力使明显的东西快。最好保持python的超级可读性,而不是在一个比C慢很多很多倍的解释器中使用比C快一点的复杂代码。1)我认为您的语法是错误的——看起来您想创建一个字典,但实际上您正在尝试创建一个集,这将失败。2) 它不是O(n logn);字典是具有分期O(1)查找的哈希映射。可能需要类似于{x['id']:x for x in a}
的东西来构建dict而不是一组元组。也可能意味着交换a和b,并且v=lookup['id']
将在缺少键时键入error,如果v不是None,则永远不会到达。在准备使用之前,这确实需要一些调整。@DSM-是的,我现在已经解决了。谢谢