【问题标题】:Return first N key:value pairs from dict从 dict 返回前 N 个键:值对
【发布时间】:2011-12-19 18:34:20
【问题描述】:

考虑以下字典,d:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

我想从 d 中返回前 N 个键:值对(在本例中为 N

【问题讨论】:

  • 小心。答案似乎有很多错误信息。我的测试表明没有一个解决方案比list(d.items())[:4] 更快。 list() 是许多答案的底层实现。
  • 对于那些想知道的人, list() 实际上将给定的字典转换为这样的列表: new_list = [('a', 3), ('b', 2),(' c', 3)......]

标签: python dictionary


【解决方案1】:

您可以通过在字典上调用.items() 来获取字典项。然后将其转换为 list 并从那里获得前 N 项,就像在任何列表中一样。

以下代码打印字典对象的前 3 项

例如

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

first_three_items = list(d.items())[:3]

print(first_three_items)

输出:

[('a', 3), ('b', 2), ('c', 3)]

【讨论】:

    【解决方案2】:

    d 是您的字典,n 是印刷号码:

    for idx, (k, v) in enumerate(d):
      if idx == n: break
      print((k, v))
    

    将您的字典转换为列表可能会很慢。你的字典可能太大了,你不需要为了打印一些第一个而把它全部转换。

    【讨论】:

    • for 循环 for idx, (k, v) in enumerate(d): 应该是 for idx, (k, v) in enumerate(d.items()): 以便返回 (k,v) 元组?
    【解决方案3】:

    对于 Python 3.8,正确答案应该是:

    import more_itertools
    
    d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
    
    first_n = more_itertools.take(3, d.items())
    print(len(first_n))
    print(first_n)
    

    谁的输出是:

    3
    [('a', 3), ('b', 2), ('c', 3)]
    

    当然是在pip install more-itertools 之后。

    【讨论】:

    • first_n = dict(more_itertools.take(3, d.items()))
    【解决方案4】:
    def GetNFirstItems(self):
        self.dict = {f'Item{i + 1}': round(uniform(20.40, 50.50), 2) for i in range(10)}#Example Dict
        self.get_items = int(input())
        for self.index,self.item in zip(range(len(self.dict)),self.dict.items()):
            if self.index==self.get_items:
              break
            else:
                print(self.item,",",end="")
    

    不寻常的方法,因为它给出了极高的 O(N) 时间复杂度。

    【讨论】:

      【解决方案5】:

      在 py3 中,这可以解决问题

      {A:N for (A,N) in [x for x in d.items()][:4]}
      

      {'a': 3, 'b': 2, 'c': 3, 'd': 4}

      【讨论】:

        【解决方案6】:

        我已经尝试了上面的一些答案,并注意到其中一些是版本相关的,在 3.7 版中不起作用。

        我还注意到,从 3.6 开始,所有字典都按插入项目的顺序排序。

        尽管从 3.6 开始对字典进行排序,但您希望使用有序结构的某些语句似乎不起作用。

        最适合我的 OP 问题的答案。

        itr = iter(dic.items())
        lst = [next(itr) for i in range(3)]
        

        【讨论】:

        • 仅供参考,比 lst = list(d.items())[:N] 慢 5 倍
        • @BSalita 虽然对于小型词典来说确实如此,但对于大型词典来说,性能变得更加有趣,因为这里发布的解决方案(原则上)渐近更快。在实践中,即使是庞大的字典(1000 万个元素),它也差不多。
        【解决方案7】:

        要从 Python 字典中获取前 N 个元素,可以使用以下代码行:

        list(dictionaryName.items())[:N]
        

        在您的情况下,您可以将其更改为:

        list(d.items())[:4]
        

        【讨论】:

          【解决方案8】:

          没有“前 n”个键这样的东西,因为 dict 不记得先插入了哪些键。

          你可以得到 any n 个键值对:

          n_items = take(n, d.iteritems())
          

          这使用来自itertools recipestake 的实现:

          from itertools import islice
          
          def take(n, iterable):
              "Return first n items of the iterable as a list"
              return list(islice(iterable, n))
          

          在线查看:ideone


          Python 3.6 更新

          n_items = take(n, d.items())
          

          【讨论】:

          • 我相信iteritems应该被items替换为Python 3的人
          • 这里是初学者 - take() 是 Python 代码库的一部分吗?或者,它纯粹是您在此处的答案中定义的功能吗?问它是否是代码库的一部分,我无法找到/导入它。 :)
          • 这个答案不再正确。 Python dicts 现在保留插入顺序,这是明确记录的。
          • @ScottBorden take() 现在属于 more-itertools 包 - stackoverflow.com/a/64009729/1396334
          • 此答案在 python 3.7+ 中不再有效请参阅我的更新答案stackoverflow.com/a/64516802/7339624
          【解决方案9】:

          这可能不是很优雅,但对我有用:

          d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
          
          x= 0
          for key, val in d.items():
              if x == 2:
                  break
              else:
                  x += 1
                  # Do something with the first two key-value pairs
          

          【讨论】:

            【解决方案10】:

            只需使用 zip 添加答案,

            {k: d[k] for k, _ in zip(d, range(n))}
            

            【讨论】:

              【解决方案11】:

              考虑一个字典

              d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
              
              from itertools import islice
              n = 3
              list(islice(d.items(),n))
              

              islice 可以解决问题 :) 希望有帮助!

              【讨论】:

                【解决方案12】:

                检索任何内容的一种非常有效的方法是将列表或字典推导与切片相结合。如果您不需要订购项目(您只需要 n 个随机对),您可以使用这样的字典理解:

                # Python 2
                first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
                # Python 3
                first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
                

                通常,这样的推导总是比等效的“for x in y”循环运行得更快。此外,通过使用 .keys() 制作字典键列表并对该列表进行切片,您可以避免在构建新字典时“接触”任何不必要的键。

                如果您不需要键(只有值),您可以使用列表推导:

                first2vals = [v for v in mydict.values()[:2]]
                

                如果您需要根据它们的键对值进行排序,那就更麻烦了:

                first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
                

                或者如果您也需要密钥:

                first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
                

                【讨论】:

                • 如果你想选择 N 多个 key:value 对作为字典而不是列表,这个是一个更好的解决方案
                • @fermat4214 当我运行这些命令时,如果我的整个字典都打印出来了,这是个问题吗?
                • list(mydict)[:2] 如果您不需要对字典进行排序而只需要前 2 个元素,则很浪费。如果字典有 1 百万个 k-v 对怎么办?将整个内容转换为列表是昂贵的。 Mark Byers 的解决方案要好得多。
                • 这应该是解决方案!
                【解决方案13】:

                对于 Python 3 及以上版本,选择前 n 对

                n=4
                firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}
                

                【讨论】:

                  【解决方案14】:
                  foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
                  iterator = iter(foo.items())
                  for i in range(3):
                      print(next(iterator))
                  

                  基本上就是把视图(dict_items)变成一个迭代器,然后用next()进行迭代。

                  【讨论】:

                  • 很棒的答案,这是此页面上唯一对我有用且可读的答案。此外,我可以验证这适用于 Python 3,而某些较旧的答案似乎并不适用。
                  【解决方案15】:

                  字典没有顺序,所以在选择前 N 个键值对之前,让它排序。

                  import operator
                  d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
                  d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
                  #itemgetter(0)=sort by keys, itemgetter(1)=sort by values
                  

                  现在我们可以检索前 'N' 个元素:,使用这样的方法结构:

                  def return_top(elements,dictionary_element):
                      '''Takes the dictionary and the 'N' elements needed in return
                      '''
                      topers={}
                      for h,i in enumerate(dictionary_element):
                          if h<elements:
                              topers.update({i:dictionary_element[i]})
                      return topers
                  

                  要获得前 2 个元素,只需使用以下结构:

                  d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
                  d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
                  d=return_top(2,d)
                  print(d)
                  

                  【讨论】:

                    【解决方案16】:

                    这里没看到。如果您只需要从字典中获取一些元素,则不会被排序,而是最简单的语法。

                    n = 2
                    {key:value for key,value in d.items()[0:n]}
                    

                    【讨论】:

                    • 我试过你的代码,但我得到了这个错误:TypeError: 'dict_items' object is not subscriptable{key:value for key,value in stocks.items()[0:n]}(股票是我字典的名称)
                    • @Moondra - 在遍历字典项目之前必须转换为列表。上面的代码,如果 {key:value for key,value in list(d.items())[0:n]} 行有效
                    • {A:N for (A,N) in [x for x in d.items()][:4]}
                    【解决方案17】:

                    请参阅PEP 0265 排序字典。然后使用前面提到的可迭代代码。

                    如果您需要在排序后的键值对中提高效率。使用不同的数据结构。也就是说,它保持排序顺序和键值关联。

                    例如

                    import bisect
                    
                    kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
                    bisect.insort_left(kvlist, ('d', 4))
                    
                    print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
                    

                    【讨论】:

                      【解决方案18】:

                      这取决于在您的情况下什么是“最有效的”。

                      如果您只想要一个庞大字典 foo 的半随机样本,请使用 foo.iteritems() 并从中获取尽可能多的值,这是一种惰性操作,可避免创建显式的键或项列表.

                      如果您需要先对键进行排序,则无法使用 keys = foo.keys(); keys.sort()sorted(foo.iterkeys()) 之类的东西,您必须构建一个显式的键列表。然后切片或迭代前 N 个keys

                      顺便说一句,您为什么关心“高效”方式?你介绍过你的程序吗?如果没有,请先使用明显易于理解的方式。它很有可能会做得很好而不会成为瓶颈。

                      【讨论】:

                      • 这是一个金融程序的应用程序,我试图尽可能高效地构建每一行代码。我没有对程序进行概要分析,并且同意这可能不会成为瓶颈,但我喜欢默认情况下要求有效的解决方案。感谢您的回复。
                      【解决方案19】:

                      您可以通过多种方式解决此问题。如果顺序很重要,您可以这样做:

                      for key in sorted(d.keys()):
                        item = d.pop(key)
                      

                      如果订单不是问题,您可以这样做:

                      for i in range(4):
                        item = d.popitem()
                      

                      【讨论】:

                      • 在第一个 sn-p 中,为了清楚起见,您可能应该将其称为 value 而不是 item
                      【解决方案20】:

                      Python 的dicts 没有排序,所以要求“前 N”个键是没有意义的。

                      如果您需要,collections.OrderedDict 类是可用的。您可以有效地将其前四个元素作为

                      import itertools
                      import collections
                      
                      d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
                      x = itertools.islice(d.items(), 0, 4)
                      
                      for key, value in x:
                          print key, value
                      

                      itertools.islice 允许您从任何迭代器中懒惰地获取元素切片。如果您希望结果可重用,则需要将其转换为列表或其他内容,如下所示:

                      x = list(itertools.islice(d.items(), 0, 4))
                      

                      【讨论】:

                      • 看起来不懒。花费的时间是 `list(d.items())[:4] 的 2 倍
                      猜你喜欢
                      • 1970-01-01
                      • 2015-04-12
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-11-12
                      • 2021-01-29
                      • 2019-01-29
                      • 1970-01-01
                      • 2017-03-22
                      相关资源
                      最近更新 更多