繁体   English   中英

如何比较字典列表中的多个键值?

[英]How do I compare multiple key values from a list of dictionaries?

我有一个字典列表,列表中的所有字典都具有相同的结构。 例如:

test_data = [{'id':1, 'value':'one'}, {'id':2, 'value':'two'}, {'id':3, 'value':'three'}]

我需要做的是比较这些词典中的每一个并返回基于值键对的“相似”词典。 例如,给定的关键value和值oen ,我想找到几乎相同的所有匹配的词典oen在这种情况下将是[{'id':1, 'value':'one'}]

difflib有一个函数get_close_matches ,它接近我需要的函数。 我能够使用列表推导提取特定键的值,然后将这些值与我的搜索进行比较:

values = [ item['value'] for item in test_data ]
found_vals = get_close_matches('oen', values) #returns ['one']

我需要做的是更进一步,将所有内容与原始词典重新组合在一起:

In  [1]: get_close_dicts('oen', test_data, 'value')
Out [1]: [{'id':1, 'value':'one'}]

注意:字典列表非常大,因此我希望尽可能高效/快速。

您可以在对数据运行get_close_dicts之前创建反向查找dict,这样一旦返回了一组值,就可以使用它们来查找相关的dict(s)。

如果你保证在你的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])

你可以:

return [d for d in test_data if get_close_matches('oen', [d['value'])]]

注意get_close_matches可能会返回多个结果。

无论如何,你最终会在某个时刻迭代每一本字典。 没有解决这个问题。 您可以做的是在预处理阶段完成所有工作,以便立即对函数进行实际调用。

正如ValAyal所提到的,反向查找字典在这里是一个好主意。 我正在想象一个字典value_dict ,其中key是第一个字典中的value ,该value包含完全匹配和类似value匹配。 d1d2为例,这些列表位于您要搜索的列表中。 如果

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的最终加速有望弥补它。 如果你想知道如何实现这一点,我可以在下班后再详细说明。 希望这可以让你对一个有用的数据结构有一个很好的想法,我并没有骇人听闻。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM