【问题标题】:How to find if the keys within two nested dictionaries match?如何查找两个嵌套字典中的键是否匹配?
【发布时间】:2017-02-23 11:07:21
【问题描述】:

项目目标: 将输入与预先存在的索引进行比较,并以术语或字母频率返回最接近的匹配。 基本上,所需的输出将在比较函数中使用如下索引:

 index = {'nino': {'n': '0.50', 'o': '0.25', 'i': '0.25'}, 
         'pablo': {'l': '0.20', 'p': '0.20', 'o': '0.20', 'b': '0.20', 'a': '0.20'}}

并将其与我将计算字母频率的输入字符串进行比较,以返回类似的输出,即字母频率:

{'y': '0.20', 'k': '0.20', 'o': '0.20', 'c': '0.20', 'r': '0.20'}

一旦我有了这个,我会遍历两个字典并检查每个项目都有哪些字母。 一旦它们出现,我将比较单词和属性点中的频率,然后比较结果并返回得分最高的那个。 我对代码的结尾没有任何问题。 但是,我似乎无法正确理解的是两个字典及其嵌套元素之间的迭代(该值毕竟是字典: 我已经尝试了两组方法,然后得到了两组的并集,但是我无法进行下一部分:它说集合是不可变的。

然后我尝试根据我在此处找到的答案调整代码: python dictionary match key values in two dictionaries 然后我从上面的答案中尝试了这个选项:

if all(string_index[k] == v for k, v in index.items() if k in index):

然后我得到一个关键错误,rocky(第一个键),它告诉我在某个地方它没有迭代和比较我想要比较的内容。

我被困在迭代部分。 一旦我做对了,我知道我可以完成它。 非常感谢任何提示或提示!

index={}
#Get frequency of a letter

def frequency_return(string,letter):
    count=0

    for letters in string:
       if letters==letter:
           count+=1
    return count

#Scan all letters: if a letter has not been searched then count
def get_frequency(string):
  range_string=string
  length_string=len(string)
  datastore={}
  target=0
  frequency=0
  while len(range_string)!=0:
           # datastore.append(range_string[target])
            frequency = (int(frequency_return(range_string,range_string[target]))/length_string)
            frequency = format(frequency, '.2f')
            datastore.update({range_string[target]:frequency})
            range_string = range_string.replace(range_string[target],'')
  return datastore          

def index_string(string):

    if string not in index:

      index.update({string: (get_frequency(string))})
    return index

index_string("pablo")
index_string("rocky")
index_string("rigo")
index_string("nino")

print (index)

###############################################################################################


def comparator (string, index):
  string_index=get_frequency(string)
  result={}
  if all(string_index[k] == v for k, v in index.items() if k in index):
    result.update(string_index)
  return result

print(comparator("baobab", index))

【问题讨论】:

  • 在没有完全理解您的问题的情况下...您是否考虑过collections 中的defaultdict?如果您引用一个迄今为止未知的键,defaultdict 将使用默认值创建它,而不是像标准 dict 那样提高 KeyError
  • 类似的想法是使用其get 方法访问标准目录。如果d 中没有'key' 的条目,则d.get('key','default') 返回default。如果有这样的条目,它会返回值匹配键。
  • 你想要的输出是什么?

标签: python dictionary iteration


【解决方案1】:

我认为您误导了您正在迭代的内容。由于某种原因,您得到了 KeyError Exception - 在这一行中:

if all(string_index[k] == v for k, v in index.items() if k in index):

在 for 循环中,您不会遍历 'rigo' 或 'pablo' 字典的键。相反,您正在迭代具有键的字典:'rigo', 'nino', 'rocky', 'pablo'(这是该代码中的 k)和值 {'a': '0.20', 'p': '0.20', 'b': '0.20', 'l': '0.20', 'o': '0.20'}{'i': '0.25', 'r': '0.25', 'g': '0.25', 'o': '0.25'} 等。

你可以用这个小sn-p试试:

>>> for k,v in index.items():
...     print("key is:{}, value is:{}".format(k,v))
... 
"key is:pablo, value is:{'a': '0.20', 'p': '0.20', 'b': '0.20', 'l': '0.20', 'o': '0.20'}"
"key is:rigo, value is:{'i': '0.25', 'r': '0.25', 'g': '0.25', 'o': '0.25'}"
"key is:nino, value is:{'i': '0.25', 'o': '0.25', 'n': '0.50'}"
"key is:rocky, value is:{'y': '0.20', 'c': '0.20', 'r': '0.20', 'k': '0.20', 'o': '0.20'}"

而且,这个 if 没有多大意义,好像你在迭代 index.items(),k 总是在 index.items() 中。

最后,由于 k 是值 'rigo'、'rocky'、'pablo'、'nino' 之一,这部分:

string_index[k] == v

...正在尝试评估 key 'rigo' 上的 string_index,它不是 string_index.keys() 的元素,因此程序返回异常。

按照建议,尝试重新编写代码或使用集合中的一些更好的数据结构。

【讨论】:

    【解决方案2】:

    不太清楚你想要的输出是什么,但我已经尝试过整理。

    首先,我们可以通过简单地使用Counter 来整理您计算每个单词的字母比例:

    from collections import Counter
    
    
    def get_proportions(word):
        frequencies = dict(Counter(word))
        for letter, value in frequencies.items():
            frequencies[letter] = float(value)/len(word)
        return frequencies
    

    Counter 返回它在单词中找到每个字母的次数。为了得到这个比例,我们只需将每个值除以单词的长度。为了在使用中演示这一点,如果我们这样做:

    comparison_dict = {}
    for word in ['pablo', 'rocky', 'rigo', 'nino']:
        comparison_dict[word] = get_proportions(word)
    
    print(comparison_dict)
    

    我们打印出来:

    {'rigo': {'i': 0.25, 'r': 0.25, 'g': 0.25, 'o': 0.25}, 'rocky': {'y': 0.2, 'c': 0.2, 'r': 0.2, 'k': 0.2, 'o': 0.2}, 'nino': {'i': 0.25, 'o': 0.25, 'n': 0.5}, 'pablo': {'a': 0.2, 'p': 0.2, 'b': 0.2, 'l': 0.2, 'o': 0.2}}
    

    我假设您的代码的最后一部分旨在计算出提供的单词与比较字典中的每个单词之间的某种“距离”?我假设你想要给定单词的字母值和字典单词的字母值之间的总差异,这给出了以下函数:

    def compare_to_dict(word, compare_to):
        props = get_proportions(word)
        comparison_scores = []
        for key in compare_to.keys():
            word_distance = sum(abs(props.get(letter, 0) - compare_to[key].get(letter, 0))
                                for letter in set(word + key))
            comparison_scores.append((key, word_distance))
        return sorted(comparison_scores, key=lambda x: x[1])
    

    对于给定单词和字典单词中的每个字母,我们计算两个单词的比例之间的(绝对)差异 - 即,如果我们的给定单词是 'baobab' 而我们的字典单词是 'rigo',那么字母 @ 987654329@ 贡献 0.25 (0.25-0),而字母 o 贡献 0.083333 (0.25 - 0.0166666)。我们根据这些差异的总和对其进行排序,因此返回列表中的第一个条目是字典中与给定单词“最接近”的单词。

    例如,如果我们print(compare_to_dict('baobab', comparison_dict)) 我们得到:

    [('pablo', 0.8666666666666666), ('rigo', 1.6666666666666665), ('rocky', 1.6666666666666665), ('nino', 1.6666666666666665)]
    

    建议'pablo' 是最接近'baobab' 的词。

    我不确定这是否正是您所追求的,如果不是,请告诉我。完整代码如下:

    from collections import Counter
    
    
    def get_proportions(word):
        frequencies = dict(Counter(word))
        for letter, value in frequencies.items():
            frequencies[letter] = float(value) / len(word)
        return frequencies
    
    
    def compare_to_dict(word, compare_to):
        props = get_proportions(word)
        comparison_scores = []
        for key in compare_to.keys():
            word_distance = sum(abs(props.get(letter, 0) - compare_to[key].get(letter, 0))
                                for letter in set(word + key))
            comparison_scores.append((key, word_distance))
        return sorted(comparison_scores, key=lambda x: x[1])
    
    
    comparison_dict = {}
    for word in ['pablo', 'rocky', 'rigo', 'nino']:
        comparison_dict[word] = get_proportions(word)
    
    print(comparison_dict)
    
    print(compare_to_dict('baobab', comparison_dict))
    

    【讨论】:

    • 这正是我一直在寻找的。我将深入研究计数器库。实际上,您的解决方案使用的系统比我想象的要好。谢谢!我会更多地研究像这样的库
    • @Thomasmeriaux 很高兴听到它。了解如何从头开始构建东西很好,但是 Python 的快捷方式可以大大简化事情。如果这解决了您的问题,您可以使用左侧的绿色勾号将其标记为答案,这将有助于其他人找到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 2019-05-13
    • 2019-06-13
    相关资源
    最近更新 更多