使用有序字典替换字典推导和默认字典

2 投票
1 回答
802 浏览
提问于 2025-04-18 05:04

下面的代码将一个XML文件转换成一个字典:

import xml.etree.cElementTree as et
tree = et.parse(path_to_xml)
root = tree.getroot()      
xml_dict = etree_to_dict(root)

其中:

def etree_to_dict(t):
    d = {t.tag: {} if t.attrib else None}
    children = list(t)
    if children:
        dd = defaultdict(list)

        for dc in map(etree_to_dict, children):
            for k, v in dc.iteritems():
                dd[k].append(v)
        d = {t.tag: {k:v[0] if len(v) == 1 else v for k, v in dd.iteritems()}}

    if t.attrib:
        d[t.tag].update(('@' + k, v) for k, v in t.attrib.iteritems())
    if t.text:
        text = t.text.strip()
        if children or t.attrib:
            if text:
              d[t.tag]['#text'] = text
        else:
            d[t.tag] = text
    return d

不过,上面的函数返回的是一个无序字典。我希望它能返回一个有序字典。对于如何替换一些字典推导式defaultdict的调用,我不是很清楚。

一个输入的例子可以是这个链接:http://www.w3schools.com/xml/plant_catalog.xml

有没有什么想法可以替换

1 个回答

3

collections.OrderedDict 来替代 dict 的推导式和 defaultdict 的操作其实很简单。需要注意的是,OrderedDict 的速度比普通的 dict(和 defaultdict)稍微慢一点,但这个差距是固定的,也就是说它们在处理大数据量时的表现是一样的。

与其使用 defaultdict,不如创建一个 OrderedDict,然后在需要的时候用 setdefault 来设置默认值:

dd = OrderedDict()

for dc in map(etree_to_dict, children):
    for k, v in dc.iteritems():
        dd.setdefault(k, []).append(v)

dict 的推导式替换成调用 OrderedDict,并使用一个列表或生成器表达式来生成 (key, value) 的元组,比如:

d = OrderedDict([(t.tag, OrderedDict((k, v[0] if len(v) == 1 else v)
                                     for k, v in dd.iteritems()))])

撰写回答