如何一次对字典或列表中的所有嵌套字典和列表进行排序?
How to sort all the nested dictionaries and lists inside a dictionary or list at once?
我正在尝试开发最 efficient/comprehensive 的功能,以此为目标:
Sorting every nested dictionary or list inside a dictionary or list.
注意: 我使用了 collections.OrderedDict
因为我想让它对 3.7 之前的 python 版本也有用,那些不保留的在字典中排序。
基于 的递归函数,它只对嵌套字典进行排序,我正在尝试构建一个对应的递归函数,它只对嵌套列表进行排序,然后通过使用 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)
<ipython-input-9-352b10801248> in recursively_order_dict(d)
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 无法对由 strings/numbers 和 lists/dictionaries 组成的可迭代对象进行排序,因为它不知道从 lists/dictionaries 中获取什么作为比较项.
与 strings/numbers 相比,我如何更改我的函数以使 lists/dictionaries 仅被放置在已排序的可迭代对象的 end/start 处?
简而言之,我应该如何改变我的函数,让它把上面的 dict_2
变成这个(手工编辑的)sorted_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",
}
所以,基本上,您需要制作一个关键功能,使所有容器的比较都比其他任何东西都少。为此,一个方便的值是 float('inf')
。然而,由于我们不知道我们正在排序的东西是否包含数字或字符串,我们必须将所有内容转换为一个元组,并手动映射每个字符串的序数值:map(ord, x)
下面是一个例子,如果你想让容器移动到前面(所以negative inf...:[=17=]
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 _move_containers_to_end(x):
if isinstance(x, (list, dict)):
# to put at the end, use inf, at the start, -inf
return (float('-inf'),)
elif isinstance(x, str):
return tuple(map(ord, x))
else: # assuming we only can get numbers at this point
return (x,)
def recursively_order_list(l):
ordered_list = []
for element in sorted(l, key=_move_containers_to_end):
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)
elif isinstance(iterable1, list):
ordered_iterable = recursively_orded_list(iterable1)
else:
print("%s\n is nor a list nor a dictionary.\nIts type is %s." % (iterable1, type(iterable1)) )
return ordered_iterable
以上结果为:
OrderedDict([('key1', 'value1'),
('key2', 'value2'),
('key3',
OrderedDict([('key3_1', 'value3_1'),
('key3_2', [[], [], 'value3_2_1']),
('key3_5', 'value3_5')])),
('key5', 'value5'),
('key8',
OrderedDict([('key8_1', 'value8_1'),
('key8_2', 'value8_2'),
('key8_5',
OrderedDict([('key8_5_2',
[OrderedDict(),
OrderedDict([('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')]),
OrderedDict(),
'value8_5_2_1']),
('key8_5_4',
['value8_5_a',
'value8_5_b',
'value8_5_c'])]))])),
('key9', 'value9')])
请注意,您可能想要执行以下操作:
import sys:
if sys.version_info.minor < 7:
OrderedMapping = dict
else:
from collections import OrderedDict as OrderedMapping
然后使用:
ordered_dict = OrderedMapping()
在recursively_order_dict
我正在尝试开发最 efficient/comprehensive 的功能,以此为目标:
Sorting every nested dictionary or list inside a dictionary or list.
注意: 我使用了 collections.OrderedDict
因为我想让它对 3.7 之前的 python 版本也有用,那些不保留的在字典中排序。
基于
这是我开发的:
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)
<ipython-input-9-352b10801248> in recursively_order_dict(d)
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 无法对由 strings/numbers 和 lists/dictionaries 组成的可迭代对象进行排序,因为它不知道从 lists/dictionaries 中获取什么作为比较项.
与 strings/numbers 相比,我如何更改我的函数以使 lists/dictionaries 仅被放置在已排序的可迭代对象的 end/start 处?
简而言之,我应该如何改变我的函数,让它把上面的 dict_2
变成这个(手工编辑的)sorted_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",
}
所以,基本上,您需要制作一个关键功能,使所有容器的比较都比其他任何东西都少。为此,一个方便的值是 float('inf')
。然而,由于我们不知道我们正在排序的东西是否包含数字或字符串,我们必须将所有内容转换为一个元组,并手动映射每个字符串的序数值:map(ord, x)
下面是一个例子,如果你想让容器移动到前面(所以negative inf...:[=17=]
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 _move_containers_to_end(x):
if isinstance(x, (list, dict)):
# to put at the end, use inf, at the start, -inf
return (float('-inf'),)
elif isinstance(x, str):
return tuple(map(ord, x))
else: # assuming we only can get numbers at this point
return (x,)
def recursively_order_list(l):
ordered_list = []
for element in sorted(l, key=_move_containers_to_end):
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)
elif isinstance(iterable1, list):
ordered_iterable = recursively_orded_list(iterable1)
else:
print("%s\n is nor a list nor a dictionary.\nIts type is %s." % (iterable1, type(iterable1)) )
return ordered_iterable
以上结果为:
OrderedDict([('key1', 'value1'),
('key2', 'value2'),
('key3',
OrderedDict([('key3_1', 'value3_1'),
('key3_2', [[], [], 'value3_2_1']),
('key3_5', 'value3_5')])),
('key5', 'value5'),
('key8',
OrderedDict([('key8_1', 'value8_1'),
('key8_2', 'value8_2'),
('key8_5',
OrderedDict([('key8_5_2',
[OrderedDict(),
OrderedDict([('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')]),
OrderedDict(),
'value8_5_2_1']),
('key8_5_4',
['value8_5_a',
'value8_5_b',
'value8_5_c'])]))])),
('key9', 'value9')])
请注意,您可能想要执行以下操作:
import sys:
if sys.version_info.minor < 7:
OrderedMapping = dict
else:
from collections import OrderedDict as OrderedMapping
然后使用:
ordered_dict = OrderedMapping()
在recursively_order_dict