Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort python list of dictionaries by key if key exists

Tags:

python

sorting

I have a list of dictionaries like this:

[{"foo" : "bar", "myKey" : "one"}, 
{"foo" : "bar", "myKey" : "two"}, 
{"foo" : "bar", "yourKey" : "three"}]

I'd like to sort it by a key in the dictionary if it exists.

featured = sorted(filesToWrite, key=lambda k: k["myKey"])

This doesn't work if "myKey" doesn't exist. EDIT: If myKey doesn't exist in the dictionary, I'd like it to appear at the end of the list.

I could loop through the list manually and do it myself but I'm sure there is a pythonic way to accomplish my goal without doing all that.

like image 265
Brad Avatar asked Jan 30 '14 01:01

Brad


2 Answers

Check out dict.get:

featured = sorted(filesToWrite, key=lambda k: ("myKey" not in k, k.get("myKey", None)))

Output:

[{'foo': 'bar', 'myKey': 'one'}, {'foo': 'bar', 'myKey': 'two'}, {'yourKey': 'three', 'foo': 'bar'}]

The magic happens in the key:

("myKey" in k, k.get("myKey", None)

Which is a two item tuple, like:

(True, "one")

Where the first element is True/False depending on whether or not the key is missing (True comes after False hence the not), and the second element is the value of said key, if it exists. If not, None. (that argument can be skipped, but I included it to be explicit)

like image 81
mhlester Avatar answered Nov 08 '22 20:11

mhlester


If you're really stuck (like I was, due to the structure of the data I was attempting to sort), you may want to break out of the lambda design, at least for diagnostic purposes. Only when I applied the "nonesorter" design shown here did I receive a meaningful diagnostic from Python that showed me that the thing I was sorting wasn't what I thought it was.

More generally: the "lambda"s you see above are shorthand that can be replaced by a full method definition that you can step through line by line with a debugger.

Also, somewhat misleading to the neophyte is the label key= in Python's sort syntax. This is not actually the name of a key field in the dictionary but rather a pointer to a function which will determine order, analogous to Perl's sort parameter called SUBNAME.

As Python.org's Sorting HOW TO describes it,

The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes. This technique is fast because the key function is called exactly once for each input record.

Finally, note that as others have stated, None was a legal item for comparison in Python 2 whereas with Python 3 attempting to compare to None generates a compiler exception.

like image 35
CODE-REaD Avatar answered Nov 08 '22 20:11

CODE-REaD