How to order dictionary based column?

Viewed 43

I have a column that contains dictionary like below

Column_1
{"X":5 , "Y" :10 , "Z" : 6}
{"X":0.4 , "Y": 0.1}
{"Z":0.55, "W": 7 , "X":3}
.
.
.

I need to write a Python code to sort each element in a column based on a value such as output will be like

Column_1
{"X":5 ,  "Z" : 6 ,"Y" :10 }
{"Y": 0.1, "X":0.4  }
{"Z":0.55, "X":3, "W": 7 }
.
.
.

Can someone help with that please?

I tried sorted function but it breaks at some point.

Thank you!

2 Answers

I assume that Column_1 is a list:

>>> Column_1
[{'X': 5, 'Y': 10, 'Z': 6}, {'X': 0.4, 'Y': 0.1}, {'Z': 0.55, 'W': 7, 'X': 3}]
>>> from operator import itemgetter
>>> [dict(sorted(mp.items(), key=itemgetter(1))) for mp in Column_1]
[{'X': 5, 'Z': 6, 'Y': 10}, {'Y': 0.1, 'X': 0.4}, {'Z': 0.55, 'X': 3, 'W': 7}]

My answer is assuming that the input is available as multi-line string obtained by printing, or read from a text file.

The voluminous code addresses issues with possible variation in formatting of the sorted line and reuses the original line of text keeping double quotation marks double, the precision of floats unchanged, and so on. The code uses pure standard Python to do its work and doesn't need any additional modules.

The final outcome leaves the heading line unchanged like it is shown in the question.

Another advantage of the code if compared to the other answer by Mechanic Pig is, that it doesn't rely on the order in which dictionary items are printed as this order is to my state of knowledge not guaranteed in Python.

srcTxt = """\
Column_1
{"X":5 , "Y" :10 , "Z" : 6}
{"X":0.4 , "Y": 0.1}
{"Z":0.55, "W": 7 , "X":3}"""
print(srcTxt)
print('---------------')
def sortDctTxtLine(dctTxtLine):
    dctTxtLine = dctTxtLine.strip() # to get only what you see
    assert dctTxtLine[0] == "{" and dctTxtLine[-1] == "}"
    lstTxtLine=dctTxtLine.split(',')
    lstTpls = sorted( [ (i, k, v) for i, (k,v) in  
            enumerate(eval(dctTxtLine).items()) ], key=lambda x: x[2] )
    dctTxtLine = dctTxtLine[1:-1] # strip { }
    lstTxt = dctTxtLine.split(',')
    tgtTxtLst = []
    for i, k, v in lstTpls:
        tgtTxtLst.append(lstTxt[i]) 
    tgtTxtLine = '{' + ' , '.join(tgtTxtLst) + '}'
    return tgtTxtLine
#:def
tgtTxt = '\n'.join( [ 
    line if line[0]!='{' else sortDctTxtLine(line) 
        for line in srcTxt.splitlines() ] )
print(tgtTxt)
print('---------------------------------------------------------------')
Column_1 = [{'X': 5, 'Y': 10, 'Z': 6}, {'X': 0.4, 'Y': 0.1}, {'Z': 0.55, 'W': 7, 'X': 3}]
from operator import itemgetter
print( [  dict( sorted(  mp.items(), key=itemgetter(1))  ) for mp in Column_1] )
# [{'X': 5, 'Z': 6, 'Y': 10}, {'Y': 0.1, 'X': 0.4}, {'Z': 0.55, 'X': 3, 'W': 7}]"""

gives:

Column_1
{"X":5 , "Y" :10 , "Z" : 6}
{"X":0.4 , "Y": 0.1}
{"Z":0.55, "W": 7 , "X":3}
---------------
Column_1
{"X":5  ,  "Z" : 6 ,  "Y" :10 }
{ "Y": 0.1 , "X":0.4 }
{"Z":0.55 ,  "X":3 ,  "W": 7 }
---------------------------------------------------------------
[{'X': 5, 'Z': 6, 'Y': 10}, {'Y': 0.1, 'X': 0.4}, {'Z': 0.55, 'X': 3, 'W': 7}]

As you can see from the comparison of the last lines the solution in the other answer (I have attached at the bottom of the above code for output comparison reasons) has single quotation marks and no 'artifacts' like "X":3 which turns into 'X': 3. It's not a big issue, but it could be one under unfavorable circumstances.

Related