簡體   English   中英

結合共享值和鍵的python詞典

[英]Combine python dictionaries that share values and keys

我正在根據字符串編輯距離進行一些實體匹配,我的結果是一個帶有鍵(查詢字符串)和值[類似字符串列表]的字典,基於一些評分標准。

例如:

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']
}

我已經嘗試使用鍵遍歷字典,但我不能圍繞如何迭代和比較每個字典項及其值列表(或單個值)。

這是使用collections.defaultdict和sets的一種解決方案。

所需的輸出與您擁有的輸出非常相似,並且可以輕松操作以對齊。

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'}}

感謝@IMCoins在第二個循環中操縱vw的想法。

說明

主要有3個步驟:

  1. 將值轉換為一致的集合格式,包括原始字典中的鍵和值。
  2. 循環瀏覽此詞典並將值添加到新詞典中。 如果存在與某個鍵的交集[即集合不是不相交的],則使用該鍵。 否則,添加到通過枚舉確定的新密鑰。
  3. 通過將最大長度鍵映射到值,在最終轉換中創建結果字典。

編輯:雖然表演不是這里的問題,但我冒昧地在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秒

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM