Sort dictionary according to keys

Question:

I have this dictionary:

enter image description here

but this dictionary is badly sorted, it should be:

x_11,
x_12,
x_13,
x_14, 
x_15, 
x_16, 
x_17, 
x_18, 
x_19, 
x_110,
x_21,
x_22,
x_23, 
x_24, 
x_25, 
x_26, 
x_27, 
x_28, 
x_29, 
x_210, 
x_31, x_32, x_33, x_34, x_35, x_36, x_37, x_38, x_39, x_310,

The first digit at x is the row number, the second digit at x is the column number.

Answers:

Idea is sorting by string before 3 letters and integers after 3 letters:

print (d)
{'x_11': 0, 'x_110': 1, 'x_12': 2, 'x_13': 3, 'x_21': 4, 'x_210': 5, 'x_22': 6, 'x_23': 7}


d = dict(sorted(d.items(), key=lambda x: (x[0][:3], int(x[0][3:]))))
print (d)
{'x_11': 0, 'x_12': 2, 'x_13': 3, 'x_110': 1, 'x_21': 4, 'x_22': 6, 'x_23': 7, 'x_210': 5}

Or if solution above not working and need split by _ it is possible sorting by first letter after separator and integer for another values:

d = dict(sorted(d.items(), key=lambda x: (x[0].split('_')[1][:1], int(x[0].split('_')[1][1:]))))
print (d)
{'x_11': 0, 'x_12': 2, 'x_13': 3, 'x_110': 1, 'x_21': 4, 'x_22': 6, 'x_23': 7, 'x_210': 5}
Answered By: jezrael

You can use sorted method two-times

result = dict(sorted(d.items(), key=lambda s: int(s[0].split("_")[1])))
result = dict(sorted(result.items(), key=lambda s: int(s[0].split("_")[1][0])))

Output:

{'x_11': 0, 'x_12': 0, 'x_13': 0, 'x_14': 0, 'x_15': 0, 'x_16': 0, 
 'x_17': 0, 'x_18': 0, 'x_19': 0, 'x_110': 0, 'x_21': 0, 'x_22': 0, 
 'x_23': 0, 'x_24': 0, 'x_25': 0, 'x_26': 0, 'x_27': 0, 'x_28': 0, 
 'x_29': 0, 'x_210': 0, 'x_31': 0, 'x_32': 0, 'x_33': 0, 'x_310': 0}

Explanation


  • The input dictionary:
    d = {'x_11': 0, 'x_110': 0, 'x_12': 0, 'x_13': 0, 'x_14': 0,
         'x_15': 0, 'x_16': 0, 'x_17': 0, 'x_18': 0, 'x_19': 0,
         'x_21': 0, 'x_210': 0, 'x_22': 0, 'x_23': 0, 'x_24': 0,
         'x_25': 0, 'x_26': 0, 'x_27': 0, 'x_28': 0, 'x_29': 0,
         'x_31': 0, 'x_310': 0, 'x_32': 0, 'x_33': 0}
    

 

The aim is to reach x_11, x12, x_13, ..., x_110, x_21, ... x_310

  • My approach:


    • First, I get integer part of each key (i.e. get 11 from x_11) then sort
    result = dict(sorted(d.items(), key=lambda s: int(s[0].split("_")[1])))
    

    Output:

    {'x_11': 0, 'x_12': 0, 'x_13': 0, 'x_14': 0, 'x_15': 0, 'x_16': 0, 'x_17': 0, 'x_18': 0, 'x_19': 0, 'x_21': 0, 'x_22': 0, 'x_23': 0, 'x_24': 0, 'x_25': 0, 'x_26': 0, 'x_27': 0, 'x_28': 0, 'x_29': 0, 'x_31': 0, 'x_32': 0, 'x_33': 0, 'x_110': 0, 'x_210': 0, 'x_310': 0}
    
    
    • Second, sort based on the first integer (i.e. get 1 from x_11)
    result = dict(sorted(result.items(), key=lambda s: int(s[0].split("_")[1][0])))
    

    Output:

    {'x_11': 0, 'x_12': 0, 'x_13': 0, 'x_14': 0, 'x_15': 0, 'x_16': 0, 'x_17': 0, 'x_18': 0, 'x_19': 0, 'x_110': 0, 'x_21': 0, 'x_22': 0, 'x_23': 0, 'x_24': 0, 'x_25': 0, 'x_26': 0, 'x_27': 0, 'x_28': 0, 'x_29': 0, 'x_210': 0, 'x_31': 0, 'x_32': 0, 'x_33': 0, 'x_310': 0}
    
    
Answered By: Ahx

You can use natsort.

You must install it. I used pip.

pip install natsort

from natsort import natsorted as nat

nat(d.items()) 

I used the dictionary:

d = {'x_11':93.0,'x_110':32.0,'x_15':0.0}

The output is:

[('x_11', 93.0), ('x_15', 0.0), ('x_110', 32.0)]

To get it back to dictionary just add one more step:

newdict = dict(nat(d.items()))
print(newdict)

{'x_11': 93.0, 'x_15': 0.0, 'x_110': 32.0}
Answered By: powerPixie

As you tagged pandas, let’s try creating a dataframe and sorting it by two columns; we can then cast it back as a dictionary.

#assuming your dictionary is caleld d. 
#not re-recreating your value data from image so coded all to 0.

d1 = (
    pd.DataFrame.from_dict(d, orient="index")
    .reset_index(0)
    .rename(columns={"index": "keys"})
)

d1 = d1.assign(
    order1=d1["keys"].str.split("_", expand=True)[1].astype(int),
    order2=d1["keys"].str.split("_", expand=True)[1].str[0].astype(int),
)

This yields :

     keys  0  order1  order2
0    x_11  0      11       1
1    x_12  0      12       1
2    x_13  0      13       1
3    x_14  0      14       1
4    x_15  0      15       1
5    x_16  0      16       1
6    x_17  0      17       1
7    x_18  0      18       1
8    x_19  0      19       1
9   x_110  0     110       1
10   x_21  0      21       2
11   x_22  0      22       2
12   x_23  0      23       2
13   x_24  0      24       2
14   x_25  0      25       2
15   x_26  0      26       2
16   x_27  0      27       2
17   x_28  0      28       2
18   x_29  0      29       2
19  x_210  0     210       2
20   x_31  0      31       3
21   x_32  0      32       3
22   x_33  0      33       3
23   x_34  0      34       3
24   x_35  0      35       3
25   x_36  0      36       3
26   x_37  0      37       3
27   x_38  0      38       3
28   x_39  0      39       3
29  x_310  0     310       3

sorted_dict = d1.sort_values(['order2','order1']).set_index('keys')[0].to_dict()

{'x_11': 0,
 'x_12': 0,
 'x_13': 0,
 'x_14': 0,
 'x_15': 0,
 'x_16': 0,
 'x_17': 0,
 'x_18': 0,
 'x_19': 0,
 'x_110': 0,
 'x_21': 0,
 'x_22': 0,
 'x_23': 0,
 'x_24': 0,
 'x_25': 0,
 'x_26': 0,
 'x_27': 0,
 'x_28': 0,
 'x_29': 0,
 'x_210': 0,
 'x_31': 0,
 'x_32': 0,
 'x_33': 0,
 'x_34': 0,
 'x_35': 0,
 'x_36': 0,
 'x_37': 0,
 'x_38': 0,
 'x_39': 0,
 'x_310': 0}
Answered By: Umar.H
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.