合并共享值和键的python词典

2024-09-28 03:16:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做一些基于字符串编辑距离的实体匹配,结果是一个字典,其中包含键(查询字符串)和基于一些评分标准的值[相似字符串列表]。你知道吗

例如:

results = {
  'ben' : ['benj', 'benjamin', 'benyamin'],
  'benj': ['ben', 'beny', 'benjamin'],
  'benjamin': ['benyamin'],
  'benyamin': ['benjamin'],
  'carl': ['karl'],
  'karl': ['carl'],
}

每个值也有一个对应的字典项,它是键(例如“carl”和“karl”)。你知道吗

我需要把有共同价值的元素结合起来。选择一个值作为新键(比如说最长的字符串)。在上面的例子中,我希望得到:

results = {
  'benjamin': ['ben', 'benj', 'benyamin', 'beny', 'benjamin', 'benyamin'],
  'carl': ['carl','karl']
}

我尝试过使用键遍历字典,但是我不知道如何遍历和比较每个字典项及其值列表(或单个值)。你知道吗


Tags: 字符串实体编辑距离列表字典karlresults
2条回答

编辑:尽管性能不是这里的问题,我还是冒昧地在jpp的答案和我的答案之间进行了一些测试。。。这是完整的剧本。我的脚本在17.79秒内完成测试,他的脚本在23.5秒内完成。你知道吗

import timeit

results = {
  'ben' : ['benj', 'benjamin', 'benyamin'],
  'benj': ['ben', 'beny', 'benjamin'],
  'benjamin': ['benyamin'],
  'benyamin': ['benjamin'],
  'carl': ['karl'],
  'karl': ['carl'],
}

def imcoins(result):
    new_dict = {}
    # .items() for python3x
    for k, v in results.iteritems():
        flag = False
        #   Checking if key exists...
        if k not in new_dict.keys():
            #   But then, we also need to check its values.
            for item in v:
                if item in new_dict.keys():
                    #   If we update, set the flag to True, so we don't create a new value.
                    new_dict[item].update(v)
                    flag = True
            if flag == False:
                new_dict[k] = set(v)

    #   Now, to sort our newly created dict...
    sorted_dict = {}
    for k, v in new_dict.iteritems():
        max_string = max(v)
        if len(max_string) > len(k):
            sorted_dict[max(v, key=len)] = set(v)
        else:
            sorted_dict[k] =  v

    return sorted_dict

def jpp(result):
    from collections import defaultdict

    res = {i: {k} | (set(v) if isinstance(v, list) else {v}) \
          for i, (k, v) in enumerate(results.items())}

    d = defaultdict(set)

    for i, (k, v) in enumerate(res.items()):
        for m, n in d.items():
            if n & v:
                d[m].update(v)
                break
        else:
            d[i] = v

    result = {max(v, key=len): v for k, v in d.items()}
    return result

iterations = 1000000
time1 = timeit.timeit(stmt='imcoins(results)', setup='from __main__ import imcoins, results', number=iterations)
time2 = timeit.timeit(stmt='jpp(results)', setup='from __main__ import jpp, results', number=iterations)

print time1 # Outputs : 17.7903265883
print time2 # Outputs : 23.5605850732

如果我将导入从他的函数移到全局范围,它将给出。。。你知道吗

imcoins:13.4129249463秒

jpp:21.8191823393秒

这是一个使用collections.defaultdict和集合的解决方案。你知道吗

所需的输出与您所拥有的非常相似,并且可以很容易地进行调整。你知道吗

from collections import defaultdict

results = {
  'ben' : ['benj', 'benjamin', 'benyamin'],
  'benj': ['ben', 'beny', 'benjamin'],
  'benjamin': 'benyamin',
  'benyamin': 'benjamin',
  'carl': 'karl',
  'karl': 'carl',
}

d = defaultdict(set)

for i, (k, v) in enumerate(results.items()):
    w = {k} | (set(v) if isinstance(v, list) else {v})
    for m, n in d.items():
        if not n.isdisjoint(w):
            d[m].update(w)
            break
    else:
        d[i] = w

result = {max(v, key=len): v for k, v in d.items()}

# {'benjamin': {'ben', 'benj', 'benjamin', 'beny', 'benyamin'},
#  'carl': {'carl', 'karl'}}

在第二个循环中操纵vw的想法归功于@IMCoins。你知道吗

解释

主要有3个步骤:

  1. 将值转换为一致的集合格式,包括原始字典中的键和值。你知道吗
  2. 循环浏览此词典并向新词典添加值。如果存在与某个关键点的交集[即集合不是不相交的],则使用该关键点。否则,添加到通过枚举确定的新密钥。你知道吗
  3. 通过将最大长度键映射到值,在最终转换中创建结果字典。你知道吗

相关问题 更多 >

    热门问题