切片 Python OrderedDict [英] Slicing a Python OrderedDict

查看:74
本文介绍了切片 Python OrderedDict的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,我经常需要从 Python OrderedDict(来自 collections 包).切片不起作用(抛出 TypeError: unhashable type),而迭代的替代方法很麻烦:

In my code I frequently need to take a subset range of keys+values from a Python OrderedDict (from collections package). Slicing doesn't work (throws TypeError: unhashable type) and the alternative, iterating, is cumbersome:

from collections import OrderedDict

o = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])

# want to do:
# x = o[1:3]
# need to do:
x = OrderedDict()
for idx, key in enumerate(o):
    if 1 <= idx < 3:
        x[key] = o[key]

有没有更好的方法来完成这项工作?

Is there a better way to get this done?

推荐答案

标准库中的有序 dict 不提供该功能.尽管在 collections.OrderedDict 之前已经存在了几年具有此功能的库(并且本质上提供了 OrderedDict 的超集):voidspace odictruamel.ordereddict(我是后一个包的作者,它是在 C 中重新实现的 odict):

The ordered dict in the standard library, doesn't provide that functionality. Even though libraries existed for a few years before collections.OrderedDict that have this functionality (and provide essentially a superset of OrderedDict): voidspace odict and ruamel.ordereddict (I am the author of the latter package, which is a reimplementation of odict in C):

from odict import OrderedDict as odict
p = odict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
print p[1:3]

在 ruamel.ordereddict 中,您可以放宽有序输入要求(AFAIK,如果键是有序的,您不能询问 dict 的派生词(这将是 ruamel.ordereddict 的良好补充,以识别 collection.OrderedDicts):

In ruamel.ordereddict you can relax the ordered input requirement (AFAIK you cannot ask derivative of dict if its keys are ordered (would be good addition to ruamel.ordereddict to recognise collection.OrderedDicts)):

from ruamel.ordereddict import ordereddict

q = ordereddict(o, relax=True)
print q[1:3]
r = odict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
print r[1:3]

如果你想(或不得不)留在标准库中,你可以将 collections.OrderedDict__getitem__ 子类化:

If you want (or have to) stay within the standard library you can sublass collections.OrderedDict's __getitem__:

class SlicableOrderedDict(OrderedDict):
    def __getitem__(self, k):
        if not isinstance(k, slice):
            return OrderedDict.__getitem__(self, k)
        x = SlicableOrderedDict()
        for idx, key in enumerate(self.keys()):
            if k.start <= idx < k.stop:
                x[key] = self[key]
        return x

s = SlicableOrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
print s[1:3]

当然,您可以使用 Martijn 或 Jimmy 的较短版本来获取需要返回的实际切片:

of course you could use Martijn's or Jimmy's shorter versions to get the actual slice that needs returning:

from itertools import islice
class SlicableOrderedDict(OrderedDict):
    def __getitem__(self, k):
        if not isinstance(k, slice):
            return OrderedDict.__getitem__(self, k)
        return SlicableOrderedDict(islice(self.viewitems(), k.start, k.stop))

t = SlicableOrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
print t[1:3]

或者如果你只是想在没有子类化的情况下改进所有现有的 OrderedDict:

or if you just want smarten up all existing OrderedDicts without subclassing:

def get_item(self, k):
    if not isinstance(k, slice):
        return OrderedDict._old__getitem__(self, k)
    return OrderedDict(islice(self.viewitems(), k.start, k.stop))

OrderedDict._old__getitem__ = OrderedDict.__getitem__
OrderedDict.__getitem__ = get_item

u = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
print u[1:3]

这篇关于切片 Python OrderedDict的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆