简体   繁体   中英

How to sort list of dictrionaries in the right way Python

I have list as follows:

data = [
  {'items': [
    {'key': u'3', 'id': 1, 'name': u'Typeplaatje'},
    {'key': u'2', 'id': 2, 'name': u'Aanduiding van het chassisnummer '},
    {'key': u'1', 'id': 3, 'name': u'Kilometerteller: Kilometerstand '},
    {'key': u'5', 'id': 4, 'name': u'Inschrijvingsbewijs '},
    {'key': u'4', 'id': 5, 'name': u'COC of gelijkvormigheidsattest '}
  ], 'id': 2, 'key': u'B', 'name': u'Onderdelen'},
  {'items': [
    {'key': u'10', 'id': 10, 'name': u'Koppeling'},
    {'key': u'7', 'id': 11, 'name': u'Differentieel '},
    {'key': u'9', 'id': 12, 'name': u'Cardanhoezen '},
    {'key': u'8', 'id': 13, 'name': u'Uitlaat '},
    {'key': u'6', 'id': 15, 'name': u'Batterij'}
    ], 'id': 2, 'key': u'B', 'name': u'Onderdelen'}
]

And I want to sort items by key .

Thus the wanted result is as follows:

res = [
      {'items': [
        {'key': u'1', 'id': 3, 'name': u'Kilometerteller: Kilometerstand '},
        {'key': u'2', 'id': 2, 'name': u'Aanduiding van het chassisnummer '},
        {'key': u'3', 'id': 1, 'name': u'Typeplaatje'},
        {'key': u'4', 'id': 5, 'name': u'COC of gelijkvormigheidsattest '},        
        {'key': u'5', 'id': 4, 'name': u'Inschrijvingsbewijs '},

      ], 'id': 2, 'key': u'B', 'name': u'Onderdelen'},
      {'items': [
        {'key': u'6', 'id': 15, 'name': u'Batterij'},
        {'key': u'7', 'id': 11, 'name': u'Differentieel '},
        {'key': u'8', 'id': 13, 'name': u'Uitlaat '},
        {'key': u'9', 'id': 12, 'name': u'Cardanhoezen '},
        {'key': u'10', 'id': 10, 'name': u'Koppeling'}        
        ], 'id': 2, 'key': u'B', 'name': u'Onderdelen'}
    ]

I've tried as follows:

res = []
for item in data:
  new_data = {
    'id': item['id'],
    'key': item['key'],
    'name': item['name'],
    'items': sorted(item['items'], key=lambda k : k['key']) 
  }
  res.append(new_data)

print(res)

The first is sorted fine, but the second one not.

What am I doing wrong and is there a better way of doing it?

Your sort is wrong in the second case because the keys are strings, and strings are sorted by their first character which is '1' if your key is '10' . A slight modification to your sorting function would do the trick:

'items': sorted(item['items'], key=lambda k : int(k['key'])

I'm doing an int because you want to sort them as if they are numbers. Here it is in your code:

res = []
for item in data:
  new_data = {
    'id': item['id'],
    'key': item['key'],
    'name': item['name'],
    'items': sorted(item['items'], key=lambda k : int(k['key']) )
  }
  res.append(new_data)

print(res)

And here's the result:

[{'id': 2,
  'items': [{'id': 3, 'key': '1', 'name': 'Kilometerteller: Kilometerstand '},
            {'id': 2, 'key': '2', 'name': 'Aanduiding van het chassisnummer '},
            {'id': 1, 'key': '3', 'name': 'Typeplaatje'},
            {'id': 5, 'key': '4', 'name': 'COC of gelijkvormigheidsattest '},
            {'id': 4, 'key': '5', 'name': 'Inschrijvingsbewijs '}],
  'key': 'B',
  'name': 'Onderdelen'},
 {'id': 2,
  'items': [{'id': 15, 'key': '6', 'name': 'Batterij'},
            {'id': 11, 'key': '7', 'name': 'Differentieel '},
            {'id': 13, 'key': '8', 'name': 'Uitlaat '},
            {'id': 12, 'key': '9', 'name': 'Cardanhoezen '},
            {'id': 10, 'key': '10', 'name': 'Koppeling'}],
  'key': 'B',
  'name': 'Onderdelen'}]

You need to replace the old items in the data with the sorted items based on key numerically instead of string sort. So use int(item['key']) in sort like,

>>> data
[{'items': [{'key': '1', 'id': 3, 'name': 'Kilometerteller: Kilometerstand '}, {'key': '2', 'id': 2, 'name': 'Aanduiding van het chassisnummer '}, {'key': '3', 'id': 1, 'name': 'Typeplaatje'}, {'key': '4', 'id': 5, 'name': 'COC of gelijkvormigheidsattest '}, {'key': '5', 'id': 4, 'name': 'Inschrijvingsbewijs '}], 'id': 2, 'key': 'B', 'name': 'Onderdelen'}, {'items': [{'key': '6', 'id': 15, 'name': 'Batterij'}, {'key': '7', 'id': 11, 'name': 'Differentieel '}, {'key': '8', 'id': 13, 'name': 'Uitlaat '}, {'key': '9', 'id': 12, 'name': 'Cardanhoezen '}, {'key': '10', 'id': 10, 'name': 'Koppeling'}], 'id': 2, 'key': 'B', 'name': 'Onderdelen'}]
>>>
>>> for item in data:
...   item['items'] = sorted(item['items'], key=lambda x: int(x['key']))
... 
>>> import pprint
>>> pprint.pprint(data)
[{'id': 2,
  'items': [{'id': 3, 'key': '1', 'name': 'Kilometerteller: Kilometerstand '},
            {'id': 2, 'key': '2', 'name': 'Aanduiding van het chassisnummer '},
            {'id': 1, 'key': '3', 'name': 'Typeplaatje'},
            {'id': 5, 'key': '4', 'name': 'COC of gelijkvormigheidsattest '},
            {'id': 4, 'key': '5', 'name': 'Inschrijvingsbewijs '}],
  'key': 'B',
  'name': 'Onderdelen'},
 {'id': 2,
  'items': [{'id': 15, 'key': '6', 'name': 'Batterij'},
            {'id': 11, 'key': '7', 'name': 'Differentieel '},
            {'id': 13, 'key': '8', 'name': 'Uitlaat '},
            {'id': 12, 'key': '9', 'name': 'Cardanhoezen '},
            {'id': 10, 'key': '10', 'name': 'Koppeling'}],
  'key': 'B',
  'name': 'Onderdelen'}]

So list comes with a handy method called sort which sorts itself inplace. I'd use that to your advantage:

for d in data:
    d['items'].sort(key=lambda x: int(x['key']))

Results:

[{'id': 2,
  'items': [{'id': 3, 'key': '1', 'name': 'Kilometerteller: Kilometerstand '},
            {'id': 2, 'key': '2', 'name': 'Aanduiding van het chassisnummer '},
            {'id': 1, 'key': '3', 'name': 'Typeplaatje'},
            {'id': 5, 'key': '4', 'name': 'COC of gelijkvormigheidsattest '},
            {'id': 4, 'key': '5', 'name': 'Inschrijvingsbewijs '}],
  'key': 'B',
  'name': 'Onderdelen'},
 {'id': 2,
  'items': [{'id': 15, 'key': '6', 'name': 'Batterij'},
            {'id': 11, 'key': '7', 'name': 'Differentieel '},
            {'id': 13, 'key': '8', 'name': 'Uitlaat '},
            {'id': 12, 'key': '9', 'name': 'Cardanhoezen '},
            {'id': 10, 'key': '10', 'name': 'Koppeling'}],
  'key': 'B',
  'name': 'Onderdelen'}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM