Home > Blockchain >  Python list of dict sorting move all zero at bottom
Python list of dict sorting move all zero at bottom

Time:07-13

I have a list of dictionary which I am sorting using multiple keys.

Now I want to push all the elements that have zero rank (rank is a key)

basically rank 0 must be at bottom

mylist =  [ 
{
    "score": 5.0,
    "rank": 2,
    "duration": 123,
    "amount": "18.000",
},
{
    "score": -1.0,
    "rank": 0,
    "duration": 23,
    "amount": "-8.000",
},
{
    "score": -2.0,
    "rank": 0,
    "duration": 63,
    "amount": "28.000",
},
{
    "score": 2.0,
    "rank": 1,
    "duration": 73,
    "amount": "18.000",
},
]


from operator import itemgetter
sort_fields = ['rank', 'duration']
sorted_list = sorted(mylist, key=itemgetter(*sort_fields), reverse=False)

 print(sorted_list)

current output

[{'score': -1.0, 'rank': 0, 'duration': 23, 'amount': '-8.000'}, {'score': -2.0, 'rank': 0, 'duration': 63, 'amount': '28.000'}, {'score': 2.0, 'rank': 1, 'duration': 73, 'amount': '18.000'}, {'score': 5.0, 'rank': 2, 'duration': 123, 'amount': '18.000'}]

expected output

[{'score': 2.0, 'rank': 1, 'duration': 73, 'amount': '18.000'}, {'score': 5.0, 'rank': 2, 'duration': 123, 'amount': '18.000'},{'score': -1.0, 'rank': 0, 'duration': 23, 'amount': '-8.000'}, {'score': -2.0, 'rank': 0, 'duration': 63, 'amount': '28.000'}, ]

CodePudding user response:

mylist =  [ 
{
    "score": 5.0,
    "rank": 2,
    "duration": 123,
    "amount": "18.000",
},
{
    "score": -1.0,
    "rank": 0,
    "duration": 23,
    "amount": "-8.000",
},
{
    "score": -2.0,
    "rank": 0,
    "duration": 63,
    "amount": "28.000",
},
{
    "score": 2.0,
    "rank": 1,
    "duration": 73,
    "amount": "18.000",
},
]


sorted_list = sorted(mylist, key = lambda x: (x['rank'] if x['rank'] > 0 else float('inf'),x['duration']))
 
print(sorted_list)

CodePudding user response:

You should make the key function return a tuple of values based on the precedence of the sorting criteria. Since the first of your sorting criteria is in fact whether the rank is zero, make that test the first item of the tuple. Then you got the rest, namely the rank and the duration, correctly in order:

sorted_list = sorted(mylist, key=lambda d: (d['rank'] == 0, d['rank'], d['duration'])))
  • Related