我有一个词典列表=
a = [{"ID":1, "VALUE":2},{"ID":2, "VALUE":2},{"ID":3, "VALUE":4},...]
"ID"
是每个字典的唯一标识符。考虑到列表是巨大的,检查列表中是否包含某个"ID"
的字典,如果没有附加到它,最快的方式是什么?然后更新其"VALUE"
(如果dict已经在列表中,则"VALUE"
将被更新,否则将写入某个值)
答案 0 :(得分:3)
你没有使用列表。改为使用字典,将id映射到嵌套字典:
a = {
1: {'VALUE': 2, 'foo': 'bar'},
42: {'VALUE': 45, 'spam': 'eggs'},
}
请注意,您不需要在嵌套字典中包含ID
键;这样做会是多余的。
现在您可以查看是否存在密钥:
if someid in a:
a[someid]['VALUE'] = newvalue
我确实假设您的ID
键不一定是序号。我还假设您需要存储VALUE
以外的其他信息;否则只需将ID
映射到VALUE
的平面字典就足够了。
字典允许您在O(1)时间内按键查找值(恒定时间与字典大小无关)。列表允许您在固定时间内查找元素,但只有在知道索引时才。
如果您不必并且必须扫描列表,则进行O(N)操作,其中N是元素的数量。您需要查看列表中的每个字典以查看它是否与ID
匹配,如果ID
不存在,则表示您必须从头到尾进行搜索。字典仍然会在O(1)时间告诉你密钥不在那里。
答案 1 :(得分:1)
如果可以,请按照其他答案的建议转换为字典,但如果您有理由*不更改存储项目的数据结构,请执行以下操作:
items = [{"ID":1, "VALUE":2}, {"ID":2, "VALUE":2}, {"ID":3, "VALUE":4}]
def set_value_by_id(id, value):
# Try to find the item, if it exists
for item in items:
if item["ID"] == id:
break
# Make and append the item if it doesn't exist
else: # Here, `else` means "if the loop terminated not via break"
item = {"ID": id}
items.append(id)
# In either case, set the value
item["VALUE"] = value
*我能想到的一些有效理由包括保留商品的顺序和允许具有相同ID的重复商品。有关使字典符合这些要求的方法,您可能需要查看OrderedDict和this answer about duplicate keys。
答案 2 :(得分:0)
将列表转换为dict,然后检查值会更有效。
d = dict((item['ID'], item['VALUE']) for item in a)
for new_key, new_value in new_items:
if new_key not in d:
d[new_key] = new_value
答案 3 :(得分:0)
还需要更新密钥:
d = dict((item['ID'], item['VALUE']) for item in a)
for new_key, new_value in new_items:
d.setdefault(new_key, 0)
d[new_key] = new_value
答案 4 :(得分:0)
在不改变数据结构的情况下回答你提出的问题,没有真正更快的方式来查看没有循环并检查每个元素并为每个元素执行字典查找 - 但是你可以将循环推送到Python运行时而不是使用Python的for
循环。
如果最终结果更快,我还没试过。
a = [{"ID":1, "VALUE":2},{"ID":2, "VALUE":2},{"ID":3, "VALUE":4}]
id = 2
tmp = filter(lambda d: d['ID']==id, a)
# the filter will either return an empty list, or a list of one item.
if not tmp:
tmp = {"ID":id, "VALUE":"default"}
a.append(tmp)
else:
tmp = tmp[0]
# tmp is bound to the found/new dictionary