【问题标题】:New dict of top n values (and keys) from dictionary (Python)来自字典(Python)的前 n 个值(和键)的新字典
【发布时间】:2016-11-11 04:35:32
【问题描述】:

我有一本姓名字典和姓名在电话簿中出现的次数:

names_dict = {
    'Adam': 100,
    'Anne': 400,
    'Britney': 321,
    'George': 645,
    'Joe': 200,
    'John': 1010,
    'Mike': 500,
    'Paul': 325,
    'Sarah': 150
}

最好不使用sorted(),我想遍历字典并创建一个仅包含前五个名称的新字典:

def sort_top_list():
  # create dict of any 5 names first
  new_dict = {}
  for i in names_dict.keys()[:5]:
    new_dict[i] = names_dict[i]:

  # Find smallest current value in new_dict
  # and compare to others in names_dict
  # to find bigger ones; replace smaller name in new_dict with bigger name
  for k,v in address_dict.iteritems():
    current_smallest = min(new_dict.itervalues())
    if v > current_smallest:
      # Found a bigger value; replace smaller key/ value in new_dict with larger key/ value
      new_dict[k] = v
      # ?? delete old key/ value pair from new_dict somehow

我似乎能够创建一个新字典,每当我们遍历 names_dict 并找到一个高于我们在 new_dict 中的名称/计数时,它就会获得一个新的键/值对。但是,在我们从 names_dict 中添加较大的之后,我不知道如何从 new_dict 中删除较小的。

有没有更好的方法 - 无需导入特殊库或使用 sorted() - 来遍历字典并创建具有最高值的前 N ​​个键的新字典?

【问题讨论】:

  • 您有什么特别的原因不想使用sorted
  • 这只是一个练习。我知道 sorted 被大量使用,但我想看看是否有可能没有任何“额外”的东西,比如 sorted(字典迭代器,如果可以的话)。我在 SO 上看到了一些此类问题的答案,但他们使用的是 sorted。
  • 你可以循环遍历字典(或它的硬拷贝)并每次弹出最大值,五次。只要记住每次更换最高温度时都要存储密钥
  • 没有什么可以阻止你自己做。您可能只需编写自己的排序并将d.items() 传递给它。

标签: python


【解决方案1】:

您应该使用heapq.nlargest() function 来实现此目的:

import heapq
from operator import itemgetter

top_names = dict(heapq.nlargest(5, names_dict.items(), key=itemgetter(1)))

这使用更有效的算法(O(NlogK) 用于大小为 N 的 dict 和 K 个顶部项目)将前 5 个项目提取为 (key, value) 元组,然后将其传递给 dict() 以创建一个新的字典。

演示:

>>> import heapq
>>> from operator import itemgetter
>>> names_dict = {'Adam': 100, 'Anne': 400, 'Britney': 321, 'George': 645, 'Joe': 200, 'John': 1010, 'Mike': 500, 'Paul': 325, 'Sarah': 150}
>>> dict(heapq.nlargest(5, names_dict.items(), key=itemgetter(1)))
{'John': 1010, 'George': 645, 'Mike': 500, 'Anne': 400, 'Paul': 325}

您可能想改用collections.Counter() classCounter.most_common() method 将使您的用例易于解决。该方法的实现在后台使用heapq.nlargest()

这些不是特殊库,它们是 Python 标准库的一部分。否则,您必须自己实现 binary heap 才能实现此目的。除非您专门研究此算法,否则重新实现您自己的算法没有什么意义,Python implementation 已针对某些关键功能使用extension written in C 进行了高度优化)。

【讨论】:

  • 它们似乎已排序,但在一般情况下实际上并非如此,对吧?这毕竟只是一个字典。还有为什么不Collections.Ordereddict(sorted(...))?是不是因为您必须在之后通过跳转到 list 然后返回“切片”它?
  • @Ev.Kounis 我使用了 Python 3.6,其中新的 dict 实现恰好保留了输入顺序。
  • 哇,不知道。也许值得一提!谢谢。 +1
  • @Ev.Kounis sorted 必须做更多的工作,因为它必须将所有元素按顺序排列,而不仅仅是前 5 个。
  • @kevingduck:正如我所说,你可以自己实现一个堆。这并不难,heapq module source 是可用的。
【解决方案2】:

我不知道,为什么您不想使用 sort 并且解决方案并不完美,甚至与您的问题不完全匹配,但我希望它可以启发您找到自己的实现。我认为这只是您遇到的真正问题的一个简短示例。

但是正如您在另一个答案中看到的那样:通常最好使用之前编写的代码,而不是自己做所有事情。

names_dict = {'Joe' : 200, 'Anne': 400, 'Mike': 500, 'John': 1010, 'Sarah': 150, 'Paul': 325, 'George' : 645, 'Adam' : 100, 'Britney': 321}

def extract_top_n(dictionary, count):
    #first step: Find the topmost values
    highest_values = []
    for k,v in dictionary.iteritems():
        print k,v, highest_values, len(highest_values)
        highest_values.append(v)
        l = len(highest_values)
        for i in range(l-1):
            print i,l
            if l-i < 1:
                break
            if highest_values[l-i-1]>highest_values[l-i-2]:
                temp = highest_values[l-i-2]
                highest_values[l-i-2] = highest_values[l-i-1]
                highest_values[l-i-1] = temp
        highest_values = highest_values [:count]

    #fill the dirctionary with all entries at least as big as the smallest of the biggest
    #but pay attention: If there are more than 2 occurances of one of the top N there will be more than N entries in the dictionary
    last_interesting = highest_values[len(highest_values)-1]
    return_dictionary = {}    
    for k,v in dictionary.iteritems():
        if v >= last_interesting:
            return_dictionary[k] = v
    return return_dictionary

print extract_top_n(names_dict,3)        

【讨论】:

    猜你喜欢
    • 2014-05-27
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 2011-07-11
    相关资源
    最近更新 更多