Search code examples
python-3.xsortingoperatorsnonetype

Sorting list containing value:None, results to TypeError: '<' not supported between instances of 'NoneType' and 'str'


I've dictionary containing list of key:value pairs. How to sort the list containing key:value pairs (where value is None)

from operator import itemgetter
test = {"test":[{ "name" : "Nandini", "age" : 20}, { "name" : "Manjeet", "age" : 20 }, { "name" : None , "age" : 19 }] }
print(sorted(test["test"], key=itemgetter('name')) )

Results to TypeError: '<' not supported between instances of 'NoneType' and 'str'

Output should include None values and look like: [{ "name" : None , "age" : 19 }, { "name" : "Manjeet", "age" : 20 },{ "name" : "Nandini","age" : 20}]


Solution

  • You can use the "or" trick:

    # python 2 you can use with the itemgetter('name') 
    # python3 needs a lambda, see further below
    from operator import itemgetter
    test = {"test":[{ "name" : "Nandini", "age" : 20}, 
                    { "name" : "Manjeet", "age" : 20 }, 
                    { "name" : None , "age" : 19 }] }
    
    
    # supply a default value that can be compared - here "" is a good one
    print(sorted(test["test"], key=itemgetter('name') or "") )
    

    to get:

    [{'age': 19, 'name': None}, 
     {'age': 20, 'name': 'Manjeet'}, 
     {'age': 20, 'name': 'Nandini'}]
    

    You essentially supply a default value for None`s (and empty strings - it operates on the Truthy-ness of the value).

    For python 3 you would need to use a lambda instead:

    print(sorted(test["test"], key=lambda x: x['name'] or ""  ))  
    

    More infos:

    Here the lambda is kindof like the itemgetter() - x is each inner dict of the list, x["name"] is the value you want as key and if that is Falsy (None, "") it will use whatever you supply after the or:

    print(None or "works")
    print("" or "works as well")