为了账号安全,请及时绑定邮箱和手机立即绑定

如何重写此函数以实现OrderedDict?

如何重写此函数以实现OrderedDict?

桃花长相依 2019-11-19 15:22:14
我有以下功能,可以完成将XML文件解析为字典的工作。不幸的是,由于不对Python字典进行排序,因此我无法按需要在各个节点之间循环。如何更改此值,使其输出有序字典,当与循环时,该字典反映节点的原始顺序for。def simplexml_load_file(file):    import collections    from lxml import etree    tree = etree.parse(file)    root = tree.getroot()    def xml_to_item(el):        item = None        if el.text:            item = el.text        child_dicts = collections.defaultdict(list)        for child in el.getchildren():            child_dicts[child.tag].append(xml_to_item(child))        return dict(child_dicts) or item    def xml_to_dict(el):        return {el.tag: xml_to_item(el)}    return xml_to_dict(root)x = simplexml_load_file('routines/test.xml')print xfor y in x['root']:    print y输出:{'root': {    'a': ['1'],    'aa': [{'b': [{'c': ['2']}, '2']}],    'aaaa': [{'bb': ['4']}],    'aaa': ['3'],    'aaaaa': ['5']}}aaaaaaaaaaaaaaa我如何实现collections.OrderedDict以便可以确定节点的正确顺序?XML文件供参考:<root>    <a>1</a>    <aa>        <b>            <c>2</c>        </b>        <b>2</b>    </aa>    <aaa>3</aaa>    <aaaa>        <bb>4</bb>    </aaaa>    <aaaaa>5</aaaaa></root>
查看完整描述

3 回答

?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

你可以使用新的将其加入到标准库的子模块2.7版本✶。实际上,您需要的是一个不存在的+ 组合-但可以通过如下所示的子类创建一个+ 组合:OrderedDictdictcollectionsOrdereddefaultdictOrderedDict


✶如果您的Python版本没有该版本,则OrderedDict应该可以使用Raymond Hettinger的Py2.4 ActiveState食谱的有序词典作为基类。


import collections


class OrderedDefaultdict(collections.OrderedDict):

    """ A defaultdict with OrderedDict as its base class. """


    def __init__(self, default_factory=None, *args, **kwargs):

        if not (default_factory is None

                or isinstance(default_factory, collections.Callable)):

            raise TypeError('first argument must be callable or None')

        super(OrderedDefaultdict, self).__init__(*args, **kwargs)

        self.default_factory = default_factory  # called by __missing__()


    def __missing__(self, key):

        if self.default_factory is None:

            raise KeyError(key,)

        self[key] = value = self.default_factory()

        return value


    def __reduce__(self):  # optional, for pickle support

        args = (self.default_factory,) if self.default_factory else tuple()

        return self.__class__, args, None, None, self.iteritems()


    def __repr__(self):  # optional

        return '%s(%r, %r)' % (self.__class__.__name__, self.default_factory,

                               list(self.iteritems()))


def simplexml_load_file(file):

    from lxml import etree


    tree = etree.parse(file)

    root = tree.getroot()


    def xml_to_item(el):

        item = el.text or None

        child_dicts = OrderedDefaultdict(list)

        for child in el.getchildren():

            child_dicts[child.tag].append(xml_to_item(child))

        return collections.OrderedDict(child_dicts) or item


    def xml_to_dict(el):

        return {el.tag: xml_to_item(el)}


    return xml_to_dict(root)


x = simplexml_load_file('routines/test.xml')

print(x)


for y in x['root']:

    print(y)

测试XML文件产生的输出如下所示:


{'root':

    OrderedDict(

        [('a', ['1']),

         ('aa', [OrderedDict([('b', [OrderedDict([('c', ['2'])]), '2'])])]),

         ('aaa', ['3']),

         ('aaaa', [OrderedDict([('bb', ['4'])])]),

         ('aaaaa', ['5'])

        ]

    )

}


a

aa

aaa

aaaa

aaaaa

我认为这接近您想要的。


小更新:


添加了一种__reduce__()方法,该方法将允许对类的实例进行正确的酸洗和酸洗。这个问题不是必需的,但是是类似的问题。


查看完整回答
反对 回复 2019-11-19
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

martineau的食谱对我有用,但是从DefaultDict继承的copy()方法有问题。以下方法可解决此缺陷:


class OrderedDefaultDict(OrderedDict):

    #Implementation as suggested by martineau


    def copy(self):

         return type(self)(self.default_factory, self)

请考虑,此实现没有深度复制,这对于默认词典来说尤其如此,在大多数情况下是正确的选择


查看完整回答
反对 回复 2019-11-19
  • 3 回答
  • 0 关注
  • 532 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信