【问题标题】:Python select ith element in OrderedDictPython在OrderedDict中选择第i个元素
【发布时间】:2014-05-01 21:32:57
【问题描述】:

我有一个按字母顺序排列字典的 sn-p 代码。 有没有办法在有序字典中选择第 i 个键并返回其对应的值?即

import collections
initial = dict(a=1, b=2, c=2, d=1, e=3)
ordered_dict = collections.OrderedDict(sorted(initial.items(), key=lambda t: t[0]))
print(ordered_dict)

OrderedDict([('a', 1), ('b', 2), ('c', 2), ('d', 1), ('e', 3)])

我想在……的脉络中发挥一些作用

select = int(input("Input dictionary index"))
#User inputs 2
#Program looks up the 2nd entry in ordered_dict (c in this case)
#And then returns the value of c (2 in this case)

如何做到这一点? 谢谢。

(类似于Accessing Items In a ordereddict,但我只想输出键值对的值。)

【问题讨论】:

  • 试试ordered_dict[ordered_dict.keys()[index]]
  • @IonutHulub,我尝试了(没有用户输入位) print(ordered_dict[ordered_dict.keys()[2]]) 并收到错误,TypeError:“KeysView”对象不支持索引。
  • lambdab 之前写入d
  • @DanielLee 抱歉,已更正。
  • 如果输入是一个小索引,你可以避免对整个initial字典进行排序,使用heapq:result = initial[heapq.nsmallest(select+1, initial)[-1]]

标签: python python-3.x ordereddictionary


【解决方案1】:

在这里使用itertools.islice 很有效,因为我们不必为了下标而创建任何中间列表。

from itertools import islice
print(next(islice(ordered_dict.items(), 2, None)))

如果你只想要价值,你可以这样做

print ordered_dict[next(islice(ordered_dict, 2, None))]

【讨论】:

  • 啊,不是我想要的。您的方法返回键值对,但我只希望代码返回 键的值
  • +1。 islice 更可取,但对于小型字典,list(ordered_dict.values())[2] 可能更快,也就是说,在测量之前不要假设更快
  • @JFSebastian,有趣的是,是什么让 islice 更适合小型词典?只是代码背后的逻辑还是其他什么?
  • @Pingk He 说,islice 更可取,但不适用于小字典
  • 对不起,我读错了,但是与 list 相比,是什么让它更快/更慢? @thefourtheye
【解决方案2】:

在 Python 2 中:

如果你想访问密钥:

>>> ordered_dict = OrderedDict([('a', 1), ('b', 2), ('c', 2), ('d', 1), ('e', 3)])
>>> ordered_dict.keys()[2]
'c'

如果要访问值:

>>> ordered_dict.values()[2]
2

如果您使用的是 Python 3,则可以通过将 keys 方法返回的 KeysView 对象包装为列表来转换它:

>>> list(ordered_dict.keys())[2]
'c'
>>> list(ordered_dict.values())[2]
2

不是最漂亮的解决方案,但它有效。

【讨论】:

    【解决方案3】:

    不要小看一个普通的 'ole for 循环:

    from collections import OrderedDict
    
    od=OrderedDict([('a', 1), ('b', 2), ('c', 2), ('d', 1), ('e', 3)])
    
    def ith(od, tgt):
        for i, t in enumerate(od.items()):
            if i==tgt:
                print('element {}\'s key is "{}"'.format(i,t[0]))
                break
        else:
            print('element {} not found'.format(tgt)) 
    
    ith(od, 2)
    # element 2's key is "c"
    ith(od, 20) 
    # element 20 not found
    

    这里的好处是,一旦找到所需的元素,循环就会中断,如果没有找到,则返回合理的结果......

    缺点是不支持相对切片。

    【讨论】:

      【解决方案4】:

      您必须使用 OrderedDict 还是只需要支持索引的类 dict 类型?如果是后者,那么考虑一个排序的 dict 对象。 SortedDict 的一些实现(根据键排序顺序对对进行排序)支持快速第 n 个索引。例如,sortedcontainers 项目有一个带有随机访问索引的SortedDict 类型。

      在你的情况下,它看起来像:

      >>> from sortedcontainers import SortedDict
      >>> sorted_dict = SortedDict(a=1, b=2, c=2, d=1, e=3)
      >>> print sorted_dict.iloc[2]
      'c'
      

      如果您进行大量查找,这将比重复迭代到所需索引快很多

      【讨论】:

      • 非常感谢,我将来可能会使用它,但是我记录为正确答案的方法与此方法非常相似。不过我很好奇,如果我更改其中一个 k-v 对的值,字典会保持有序,还是会像标准字典一样重新排列?
      • 是的,它会自动保持按键排序。如果您对字典进行编辑然后编制索引,这将比公认的解决方案快得多。
      • 太棒了,下次我可能会用这个。我不认为我会改变接受的答案,但我会投票给你。
      【解决方案5】:

      你可以按照这些思路做一些事情(od 是有序的字典):

      def get_idx(od, idx):
         from itertools import islice
         idx = (idx + len(od)) % len(od)
         t = islice(od.items(), idx, idx + 1)
         return next(t)
      
      >>>x
      
      OrderedDict([('a', 2), ('b', 3), ('k', 23), ('t', 41), ('q', 23)])
      
      >>>get_idx(x, 1)
      ('b', 3)
      >>>get_idx(x, 2)
      ('k', 23)
      >>>get_idx(x, 4)
      ('q', 23)
      >>>get_idx(x, -1)
      ('q', 23)
      >>>get_idx(x, -2)
      ('t', 41)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-08
        • 2019-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多