递归地按键对嵌套的OrderedDict进行排序

时间:2014-03-28 19:29:36

标签: python sorting recursion ordereddictionary

origOrderedDict,其中包含正常的字符串:字符串键值对,但有时值可能是另一个嵌套的OrderedDict

我希望按键排序orig,按字母顺序排序(升序),然后递归

规则:

  • 假设关键字符串不可预测
  • 假设嵌套可以无限发生,例如级别1-50都有字符串,OrderedDicts等作为值。

需要sorted算法的帮助:

import string
from random import choice


orig = OrderedDict((
    ('a', choice(string.digits)),
    ('b', choice(string.digits)),
    ('c', choice(string.digits)),
    ('special', OrderedDict((
        ('a', choice(string.digits)),
        ('b', choice(string.digits)),
        ('c', choice(string.digits)),
    )))
))

sorted_copy = OrderedDict(sorted(orig.iteritems(), ...))

self.assertEqual(orig, sorted_copy)

4 个答案:

答案 0 :(得分:17)

编辑:对于python 3.6+,@ pelson的答案更好

类似的东西:

def sortOD(od):
    res = OrderedDict()
    for k, v in sorted(od.items()):
        if isinstance(v, dict):
            res[k] = sortOD(v)
        else:
            res[k] = v
    return res

答案 1 :(得分:7)

@ acushner的解决方案现在可以在python3.6 +中简化,因为字典现在可以保留它们的插入顺序。

鉴于我们现在可以使用标准字典,现在代码如下:

def order_dict(dictionary):
    result = {}
    for k, v in sorted(dictionary.items()):
        if isinstance(v, dict):
            result[k] = order_dict(v)
        else:
            result[k] = v
    return result

因为我们可以使用标准词典,所以我们也可以使用标准词典理解,因此代码归结为:

def order_dict(dictionary):
    return {k: order_dict(v) if isinstance(v, dict) else v
            for k, v in sorted(dictionary.items())}

有关python的有序字典实现的详细信息,另请参阅https://mail.python.org/pipermail/python-dev/2016-September/146327.html。此外,声明这将是python 3.7的语言特性:https://mail.python.org/pipermail/python-dev/2017-December/151283.html

答案 2 :(得分:5)

非常类似于@ acushner的解决方案,但基于类:

from collections import OrderedDict


class SortedDict(OrderedDict):

    def __init__(self, **kwargs):
        super(SortedDict, self).__init__()

        for key, value in sorted(kwargs.items()):
            if isinstance(value, dict):
                self[key] = SortedDict(**value)
            else:
                self[key] = value

用法:

sorted_dict = SortedDict(**unsorted_dict)

答案 3 :(得分:1)

我遇到了一个非常相似的问题,即获得一个稳定的对象,因此我可以获得一个稳定的哈希,除了我的对象包含列表和字典,因此我必须对所有字典进行排序,首先对深度进行排序,然后对列表。这扩展了@acushneranswer

.once()

作为补充,如果您发现自己的对象中有需要分类的类,则可以Promise.all(...),然后def deep_sort(obj): if isinstance(obj, dict): obj = OrderedDict(sorted(obj.items())) for k, v in obj.items(): if isinstance(v, dict) or isinstance(v, list): obj[k] = deep_sort(v) if isinstance(obj, list): for i, v in enumerate(obj): if isinstance(v, dict) or isinstance(v, list): obj[i] = deep_sort(v) obj = sorted(obj, key=lambda x: json.dumps(x)) return obj ,然后jsonpickle.dumps()对其进行排序。如果很重要,那么您始终可以json.loads()deep_sort()回到开始的地方,除了排序(好,只有在Python 3.6+中才排序)。对于稳定哈希的情况,则没有必要。