Home > Enterprise >  Sorting python dictionary based on keys which is alphanumeric values
Sorting python dictionary based on keys which is alphanumeric values

Time:06-13

I am new to python. In Python, I want to sort list of dictionary items first based on 'year' key and later with key which is alphanumeric ie P1, P2, P3.

Code snippet is as follows:

[
    {"P9": 0, "year": 2023},
    {"P13": 0, "year": 2023},
    {"P10": 0, "year": 2023},
    {"P11": 121200, "year": 2022},
    {"P12": 0, "year": 2023},
]

Which first sorted by year in acending order becomes:

[
    {"P11": 121200, "year": 2022},
    {"P9": 0, "year": 2023},
    {"P13": 0, "year": 2023},
    {"P10": 0, "year": 2023},
    {"P12": 0, "year": 2023},
]

Again later sorted by period key ie, P1,P2,P3 etc becomes:

[
    {"P11": 121200, "year": 2022},
    {"P9": 0, "year": 2023},
    {"P10": 0, "year": 2023},
    {"P12": 0, "year": 2023},
    {"P13": 0, "year": 2023},
]

Above is the expected output, Now I don't know how do I sort it like this

CodePudding user response:

The sort function do all you need

You can pass a key function (a callable) for identifying the correct order. In your case:

unordered = [{'P9': 0, 'year': 2023}, {'P13': 0, 'year': 2023}, {'P10': 0, 'year': 2023}, {'P11': 121200, 'year': 2022}, {'P12': 0, 'year': 2023}]

#by year

sorted(unordered, key=lambda x: x['year'])
# out
[{'P11': 121200, 'year': 2022},
 {'P9': 0, 'year': 2023},
 {'P13': 0, 'year': 2023},
 {'P10': 0, 'year': 2023},
 {'P12': 0, 'year': 2023}]

For the period, the solution is a little bit tricky, you must identify how to select the P** key. We don't know how these dictionaries are built but doing some assumptions maybe something like:

sorted(unordered, key=lambda x: [lbl for lbl in x if lbl.startswith('P')][0] )

but here there are lacks of information to be more precise

CodePudding user response:

You can use sorted function, and specify a key function with it. But as you want to use two separate data points as keys, you can use tuple to build a key.

Because when tuples are compared, it first compares the very first entity in it, and if the first one matches, then it goes to check the second entity.

Example:

>>> (1,3) > (1, 4)
False

>>> (1, 4) < (2,2)
True

>>> (1, 4, 1) < (2, 1)
True

So, here's how you can build your key function:

>>> unordered = [{'P9': 0, 'year': 2023}, {'P13': 0, 'year': 2023}, {'P10': 0, 'year': 2023}, {'P11': 121200, 'year': 2022}, {'P12': 0, 'year': 2023}]
>>> ordered = sorted(
    unordered,
    key=lambda d: (d['year'], next(int(k[1:]) for k in d.keys() if k.startswith('P')))
)

>>> ordered
[{'P11': 121200, 'year': 2022}, {'P9': 0, 'year': 2023}, {'P10': 0, 'year': 2023}, {'P12': 0, 'year': 2023}, {'P13': 0, 'year': 2023}]

Here, I'm just assuming that you'll always have a key in the dictionary that starts with P, and the remaining part of it is an integer.

CodePudding user response:

For sorting first base years then sorting base first key of each dict you can catch number and convert to int then sorting like below:

>>> sorted(lst_dct, key=lambda x: (x['year'], int(list(x.keys())[0][1:])))
[{'P11': 121200, 'year': 2022},
 {'P9': 0, 'year': 2023},
 {'P10': 0, 'year': 2023},
 {'P12': 0, 'year': 2023},
 {'P13': 0, 'year': 2023}]
  • Related