2016/08/26

Sorting in python

How to sort lists in python? The easiest option is to use the sort method.

For example, to sort the list of vendors you can use the following procedure:

>>> devices = ['cisco', 'juniper', 'alcatel']
>>> devices.sort()
>>> devices
['alcatel', 'cisco', 'juniper']

The python sort the elements alphabetically. Ok that was a simple example. What if we have a list of IP addresses, like in example bellow.

>>> ipAddresses = ['1.1.1.1', '6.6.6.6', '10.10.10.10']
>>> ipAddresses.sort()
>>> ipAddresses
['1.1.1.1', '10.10.10.10', '6.6.6.6']

This is not correct. The problem is that python sorts elements in list alphabetically. This means that first letter in the string '10.10.10.10' is before the first letter in string '6.6.6.6'. How to solve this?

The solution is to use the key argument in the sort method. The key argument expects the function, which will be called for each element and the result of the function will be used to sort elements in the list.

We can transform the IP address into decimal form and then sort these values based on the decimal value. The solution for sorting the IP addresses can be:

>>> import ipaddr
>>> def transformToDecimal(ip):
...  ipAddress = ipaddr.IPv4Network(ip)
...  return int(ipAddress)
>>>
>>>
>>> ipAddresses
['1.1.1.1', '10.10.10.10', '6.6.6.6']
>>> ipAddresses.sort(key=transformToDecimal)
>>> ipAddresses
['1.1.1.1', '6.6.6.6', '10.10.10.10']

Now the result is as we have expected. The sort function was calling the transformToDecimal function for every element in the list. The function returned the decimal representation of the IP address, which was then used for sorting the elements in the list.

Now continue with a little more complex problem. How to sort the list of dictionaries by the values. For example, if we have the following list of dictionaries:

deviceList = [{'vendor': 'cisco', 'ipAddress': '1.1.1.1'}, {'vendor': 'juniper', 'ipAddress': '6.6.6.6'}, {'vendor': 'alcatel', 'ipAddress': '10.10.10.10'}]

How can we sort these dictionaries by the vendor. The solution could be to implement own function that return the vendor value. But the python has similiar function that is already built-in. The module is called operator. So the complete solution is:

>>> import operator
>>> getVendor = operator.itemgetter('vendor')
>>> deviceList
[{'ipAddress': '1.1.1.1', 'vendor': 'cisco'}, {'ipAddress': '6.6.6.6', 'vendor': 'juniper'}, {'ipAddress': '10.10.10.10', 'vendor': 'alcatel'}]
>>> deviceList.sort(key=getVendor)
>>> deviceList
[{'ipAddress': '10.10.10.10', 'vendor': 'alcatel'}, {'ipAddress': '1.1.1.1', 'vendor': 'cisco'}, {'ipAddress': '6.6.6.6', 'vendor': 'juniper'}]

The itemgetter method create a function that return dictionary value, of the key that is specified as an argument. In our example, we are using 'vendor' key.

So the sort option is very simple for the simple lists. But for the more complex lists you can specify your own sorting key, which could be very useful.