You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中一次性排序字典或列表内所有嵌套的字典和列表?

嵌套字典列表统一排序函数开发问题

我想要开发一款高效通用的函数,实现如下目标:

对字典或列表内部的所有嵌套字典、列表统一排序。

注意: 使用了collections.OrderedDict,目的是兼容Python 3.7之前的版本,这些版本的原生字典不保留插入顺序。

基于现有仅支持嵌套字典排序的递归函数,打算开发对应的仅支持嵌套列表排序的递归函数,再通过if分支判断待排序对象是字典还是列表,将两个函数整合使用。

初始实现代码

from collections import OrderedDict

def recursively_order_dict(d):
    ordered_dict = OrderedDict()
    for key in sorted(d.keys()):
        val = d[key]
        if isinstance(val, dict):
            val = recursively_order_dict(val)
        if isinstance(val, list):
            val = recursively_order_list(val)    
        ordered_dict[key] = val
    return ordered_dict

def recursively_order_list(l):
    ordered_list = []
    for element in sorted(l):
        if isinstance(element, list):
            element = recursively_order_list(element)
        if isinstance(element, dict):
            element = recursively_order_dict(element)
        ordered_list.append(element)
    return ordered_list 

def order_all_dicts_and_lists_in_iterable(iterable1):        
    if isinstance(iterable1, dict):
        ordered_iterable = recursively_order_dict(iterable1)            
    if isinstance(iterable1, list):
        ordered_iterable = recursively_order_list(iterable1)                   
    else:        
        print("%s\n is nor a list nor a dictionary.\nIts type is %s." % (iterable1, type(iterable1)) ) 
        return   
    return ordered_iterable    

问题复现

该函数在多数测试用例下运行正常,但处理如下字典dict_2时:

dict_2 = { 
        "key9":"value9",
        "key5":"value5",
        "key3":{
                "key3_1":"value3_1",
                "key3_5":"value3_5",
                "key3_2":[[], "value3_2_1", [] ],
                },
        "key2":"value2",
        "key8":{
                "key8_1":"value8_1",
                "key8_5":{
                            "key8_5_4":["value8_5_b", "value8_5_a", "value8_5_c"],
                            "key8_5_2":[{}, {"key8_5_2_4_2":"value8_5_2_4_2", "key8_5_2_4_1":"value8_5_2_4_1", "key8_5_2_4_5":"value8_5_2_4_5"}, "value8_5_2_1", {}],
                            },
                "key8_2":"value8_2",
                },
        "key1":"value1",
     }

sorted_dict_2 = order_all_dicts_and_lists_in_iterable(dict_2)

抛出错误:

--------------------------------------------------------------------------- TypeError                                 Traceback (most recent call last) <ipython-input-12-9cbf4414127d> in <module>
----> 1 order_all_dicts_and_lists_in_iterable(dict_2)

<ipython-input-9-352b10801248> in order_all_dicts_and_lists_in_iterable(iterable1)
     26 
     27     if isinstance(iterable1, dict):
---> 28         ordered_iterable = recursively_order_dict(iterable1)
     29         if isinstance(iterable1, list):
     30             ordered_iterable = order_all_dicts_and_lists_in_iterable(ordered_iterable)

<ipython-input-9-352b10801248> in recursively_order_dict(d)
      6         val = d[key]
      7         if isinstance(val, dict):
----> 8             val = recursively_order_dict(val)
      9         if isinstance(val, list):
---> 10             val = recursively_order_list(val)
     11         ordered_dict[key] = val
     12         return ordered_dict

<ipython-input-9-352b10801248> in recursively_order_list(l)
     14 def recursively_order_list(l):
     15     ordered_list = []
---> 16     for element in sorted(l):
     17         if isinstance(element, list):
     18             element = recursively_order_list(element)

TypeError: '<' not supported between instances of 'str' and 'list'

报错原因是Python无法对同时包含字符串/数字和列表/字典的可迭代对象排序,因为它不知道要取列表/字典的哪个属性作为比较依据。

需求

调整函数,实现与字符串/数字比较时,列表/字典排在可迭代对象的开头,最终将dict_2转换为如下预期结果:

sorted_dict_2 = { 
            "key1":"value1",
            "key2":"value2",
            "key3":{
                    "key3_1":"value3_1",
                    "key3_2":[ [],[],"value3_2_1" ],
                    "key3_5":"value3_5",                    
                    },            
            "key5":"value5",           
            "key8":{
                    "key8_1":"value8_1",
                    "key8_2":"value8_2",
                    "key8_5":{                                
                                "key8_5_2":[
                                            {},
                                            {},
                                            "value8_5_2_1",
                                            {
                                            "key8_5_2_4_1":"value8_5_2_4_1",
                                            "key8_5_2_4_2":"value8_5_2_4_2",                                               
                                            "key8_5_2_4_5":"value8_5_2_4_5"
                                            },                                                                                        
                                            ],
                                "key8_5_4":["value8_5_a", "value8_5_b", "value8_5_c"],
                            },
                    
                    },
            "key9":"value9",
         }

解决方案

核心思路是给sorted函数自定义排序键,给不同类型的元素分配优先级权重,让列表、字典的优先级高于普通字符串/数字,保证它们排在前面,同类型元素按原有规则排序。同时修正了原代码中并列判断导致的逻辑错误:

from collections import OrderedDict

def get_sort_key(element):
    # 自定义排序权重:list < dict < 其他基础类型,保证容器排在前面
    if isinstance(element, list):
        return (0, element)
    elif isinstance(element, dict):
        return (1, str(sorted(element.keys())))
    else:
        return (2, element)

def recursively_order_dict(d):
    ordered_dict = OrderedDict()
    for key in sorted(d.keys()):
        val = d[key]
        if isinstance(val, dict):
            val = recursively_order_dict(val)
        elif isinstance(val, list):
            val = recursively_order_list(val)    
        ordered_dict[key] = val
    return ordered_dict

def recursively_order_list(l):
    ordered_list = []
    # 改用自定义key排序,避免跨类型比较错误
    for element in sorted(l, key=get_sort_key):
        if isinstance(element, list):
            element = recursively_order_list(element)
        elif isinstance(element, dict):
            element = recursively_order_dict(element)
        ordered_list.append(element)
    return ordered_list 

def order_all_dicts_and_lists_in_iterable(iterable1):        
    if isinstance(iterable1, dict):
        ordered_iterable = recursively_order_dict(iterable1)            
    elif isinstance(iterable1, list):
        ordered_iterable = recursively_order_list(iterable1)                   
    else:        
        print("%s\n is not a list nor a dictionary.\nIts type is %s." % (iterable1, type(iterable1)) ) 
        return   
    return ordered_iterable    

如果需要让列表/字典排在末尾,只需要把get_sort_key里的权重顺序反过来即可:基础类型权重最低,容器权重最高。


内容的提问来源于stack exchange,提问作者Tms91

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 06:09:02