我有一个字典列表,这些字典在列表中都具有相同的结构。例如:
test_data = [{'id':1, 'value':'one'}, {'id':2, 'value':'two'}, {'id':3, 'value':'three'}]
我需要做的是比较每个词典并根据值键对返回“相似”词典。例如,给定键value
和值oen
,我想找到几乎与oen
类似的所有匹配词典,在本例中为[{'id':1, 'value':'one'}]
。values = [ item['value'] for item in test_data ]
found_vals = get_close_matches('oen', values) #returns ['one']
。
difflib
的函数get_close_matches
接近我的需要。我可以使用a list comprehension提取特定密钥的值,然后将这些值与我的搜索进行比较:
In [1]: get_close_dicts('oen', test_data, 'value')
Out [1]: [{'id':1, 'value':'one'}]
我需要做的就是更进一步,将所有内容与原始词典重新组合在一起:
{{1}}
注意:字典列表非常大,因此我希望尽可能高效/快速。
答案 0 :(得分:2)
您可以在对数据运行get_close_dicts之前创建反向查找字典,这样一旦返回了一组值,就可以使用它们来查找相关的字典。
如果你保证在你的dicts中为'value'键提供唯一值,那么你可以这样做:
reverselookup = {thedict['value']:thedict for thedict in test_data}
但是,如果您需要处理多个dicts对'value'键具有相同值的情况,那么您需要映射所有这些(这将为您提供一个dict,其中键是值'value'和值是具有该值的dicts列表):
from collections import defaultdict
reverselookup = defaultdict(list)
for testdict in test_data:
reverselookup[testdict['value']].append(testdict)
例如,如果你的测试数据中有一个额外的dict,就像这样:
>>> test_data = [{'id':1, 'value':'one'}, {'id':2, 'value':'two'},
{'id':3, 'value':'three'}, {'id':4, 'value':'three'}]
然后上面的反向查找结构会给你这个:
{
"three": [
{
"id": 3,
"value": "three"
},
{
"id": 4,
"value": "three"
}
],
"two": [
{
"id": 2,
"value": "two"
}
],
"one": [
{
"id": 1,
"value": "one"
}
]
}
然后在获得值之后,只需检索dicts(如果你有列表用例,你可以链接,如果你有第一个用例则不需要链接):
from itertools import chain
chain(*[reverselookup[val] for val in found_vals])
答案 1 :(得分:0)
你可以:
return [d for d in test_data if get_close_matches('oen', [d['value'])]]
注意get_close_matches可能会返回多个结果。
答案 2 :(得分:0)
无论如何,你最终会在某个时刻迭代每一本字典。没有解决这个问题。您可以做的是在预处理阶段完成所有工作,立即对函数进行实际调用。
正如ValAyal所提到的,反向查找字典在这里是一个好主意。我正在想象一个字典value_dict
,其中key
是第一个字典中的值,而value
包含完全匹配和类似value
匹配。以您要搜索的列表中的d1
和d2
为例。如果
d1 = {'id':1, 'value':'one'}
d2 = {'id':3, 'value':'oen'}
然后:
value_dict["one"] = {"exact": [d1], "close": [d2]}
value_dict["oen"] = {"exact": [d2], "close": [d1]}
每当您插入具有已经看到的值的字典时,您可以立即确定所有完全匹配和完全匹配(仅通过查找该值),并相应地添加到各个列表。如果您有一个之前未曾见过的新值,则必须将其与value_dict
中当前的所有值进行比较。例如,如果要添加
d3 = {'id':5, 'value':'one'}
您需要查找value_dict["one"]
并获取exact
和close
列表。这些列表包括您需要修改的所有其他value_dict
条目。您需要添加one
的完全匹配和oen
的近似匹配;您可以从返回的列表中获取这两个值。你最终得到了
value_dict["one"] = {"exact": [d1, d3], "close": [d2]}
value_dict["oen"] = {"exact": [d2], "close": [d1, d3]}
因此,一旦完成所有预处理,您的函数就会变得更简单:类似get_close_dicts(val)
(我不知道您的示例中第三个参数的作用)可以return value_dict[val]["exact"] + value_dict[val]["close"]
。你现在有一个能立即给出答案的功能。
预处理步骤非常复杂,但get_close_dicts
中的结果加速有望弥补它。如果你想知道如何实现这一点,我可以在下班后再详细说明。希望这可以让你对一个有用的数据结构有一个很好的了解,而且我并没有过分暗示这一点。