如何按主词和子词典对python词典进行排序

问题描述 投票:0回答:2

我有一本字典,用于存储我需要按国家/地区和办公地点对其进行排序的国家和办事处。我设法通过这样做按国家排序;

sorted_list = [[id, desc] for id, desc in sorted(locations.items(), key=lambda item: (item[1]['name']))

然而,当我尝试做项目[1] ['cities'] ['names']时它没有用,因为很明显索引是字符串而不是整数。

(TypeError:list indices必须是整数或切片,而不是str)

我需要做的是先按国家排序,然后按城市排序

预期产出:

奥地利 - > Gramatneusiedl /维也纳,内政部,Lenzing,Schoerfling,Weissenstein

比利时 - >安特卫普,布鲁塞尔,内政部,奥斯坦德

初始输入:

 locations = '2248': {
            'name': 'Austria',
            'cities': [{
                'OptionId': 2289,
                'name': 'Gramatneusiedl / Vienna'
            }, {
                'OptionId': 2290,
                'name': 'Lenzing'
            }, {
                'OptionId': 2291,
                'name': 'Schoerfling'
            }, {
                'OptionId': 2292,
                'name': 'Weissenstein'
            }, {
                'OptionId': 2293,
                'name': 'Home Office'
            }]
        },

    '2249': {
                'name': 'Belgium',
                'cities': [{
                    'OptionId': 9367,
                    'name': 'Oostende'
                }, {
                    'OptionId': 2294,
                    'name': 'Antwerp'
                }, {
                    'OptionId': 2295,
                    'name': 'Brussels'
                }, {
                    'OptionId': 2296,
                    'name': 'Home Office'
                }]
python sorting dictionary
2个回答
1
投票

Python中的字典键不保证顺序。你可以看到这篇SO帖子了解更多细节:Python dictionary, how to keep keys/values in same order as declared?。有办法做到这一点,根据您使用的Python版本,它可能会有所不同。

如果您只想按顺序打印项目,可以使用json库轻松管理它。

import json
ordered = {v['name']: sorted([i['name'] for i in v['cities']]) for v in locations.values()}
json.dumps(ordered, sort_keys=True)

这将打印以下结果:

{
  "Austria": [
    "Gramatneusiedl / Vienna",
    "Home Office",
    "Lenzing",
    "Schoerfling",
    "Weissenstein"
  ],
  "Belgium": [
    "Antwerp",
    "Brussels",
    "Home Office",
    "Oostende"
  ]
}

如果要在字典中维护顺序,请使用OrderedDict对象。 OrderedDicts记住插入顺序。因此,我们可以在创建最终字典之前根据name键的值对所有项进行排序。

from collections import OrderedDict
ordered = OrderedDict()
# sort each dictionary by their name field
sorted_by_country = sorted(locations.values(), key = lambda x:x['name'])
for v in sorted_by_country:
    ordered[v['name']] = sorted([i['name'] for i in v['cities']])

0
投票

你可以试试这个:

locations = {'2248': {'cities': [{'OptionId': 2289, 'name': 'Gramatneusiedl / Vienna'}, {'OptionId': 2290, 'name': 'Lenzing'}, {'OptionId': 2291, 'name': 'Schoerfling'}, {'OptionId': 2292, 'name': 'Weissenstein'}, {'OptionId': 2293, 'name': 'Home Office'}], 'name': 'Austria'}, '2249': {'cities': [{'OptionId': 9367, 'name': 'Oostende'}, {'OptionId': 2294, 'name': 'Antwerp'}, {'OptionId': 2295, 'name': 'Brussels'}, {'OptionId': 2296, 'name': 'Home Office'}], 'name': 'Belgium'}}
new_locations = {a:{c:d if isinstance(d, str) else sorted(d, key=lambda x:x['name']) for c, d in b.items()} for a, b in locations.items()}

输出:

{'2248': {'cities': [{'OptionId': 2289, 'name': 'Gramatneusiedl / Vienna'}, {'OptionId': 2293, 'name': 'Home Office'}, {'OptionId': 2290, 'name': 'Lenzing'}, {'OptionId': 2291, 'name': 'Schoerfling'}, {'OptionId': 2292, 'name': 'Weissenstein'}], 'name': 'Austria'}, '2249': {'cities': [{'OptionId': 2294, 'name': 'Antwerp'}, {'OptionId': 2295, 'name': 'Brussels'}, {'OptionId': 2296, 'name': 'Home Office'}, {'OptionId': 9367, 'name': 'Oostende'}], 'name': 'Belgium'}}

编辑:Python词典本质上是未分类的,但是,您可以使用collections.OrderedDict来补偿:

from collections import OrderedDict
new_locations = OrderedDict()
final_data = sorted(locations.items(), key=lambda x:x[-1]['name'])
for a, b in final_data:
   new_locations[a] = {'name':b['name'], 'cities':sorted(b['cities'], key=lambda x:x['name'])}

输出:

OrderedDict([('2248', {'cities': [{'OptionId': 2289, 'name': 'Gramatneusiedl / Vienna'}, {'OptionId': 2293, 'name': 'Home Office'}, {'OptionId': 2290, 'name': 'Lenzing'}, {'OptionId': 2291, 'name': 'Schoerfling'}, {'OptionId': 2292, 'name': 'Weissenstein'}], 'name': 'Austria'}), ('2249', {'cities': [{'OptionId': 2294, 'name': 'Antwerp'}, {'OptionId': 2295, 'name': 'Brussels'}, {'OptionId': 2296, 'name': 'Home Office'}, {'OptionId': 9367, 'name': 'Oostende'}], 'name': 'Belgium'})])
© www.soinside.com 2019 - 2024. All rights reserved.