I have a piece of code that looks like this:
ipCount = defaultdict(int)
for logLine in logLines:
date, serverIp, clientIp = logLine.split(\" \")
ipC
Use the key parameter of sorted to convert your ip to an integer, for example:
list_of_ips = ['192.168.204.111', '192.168.99.11', '192.168.102.105']
sorted(list_of_ips, key=lambda ip: long(''.join(["%02X" % long(i) for i in ip.split('.')]), 16))
EDIT:
Gryphius proposes a solution with the socket module, and so why not use it to make the conversion from ip to long as it is cleaner:
from socket import inet_aton
import struct
list_of_ips = ['192.168.204.111', '192.168.99.11', '192.168.102.105']
sorted(list_of_ips, key=lambda ip: struct.unpack("!L", inet_aton(ip))[0])
A clean way of handling the right order is using Pythons ipaddress module. You can transform the Strings into IPv4Address representations and sort them afterwards. Here's a working example with list objects (Tested with Python3):
import ipaddress
unsorted_list = [
'192.168.102.105',
'192.168.204.111',
'192.168.99.11'
]
new_list = []
for element in unsorted_list:
new_list.append(ipaddress.ip_address(element))
new_list.sort()
# [IPv4Address('192.168.99.11'), IPv4Address('192.168.102.105'), IPv4Address('192.168.204.111')]
print(new_list)
What are my options here?
The two obvious one that come to my mind are:
sorted()
function when you perform the ordering.Which is best depends from the amount of data you have to process (you will notice an increased performance for method #1 only for very large amount of data) and from what you will need to do with said sorted list of IP (if you preformat the strings, you might then need to change them again before feeding them as arguments to other functions, for example).
Example of preformatting
Maintain the IP as a string, but uses spaces or zeroes to solve the variable number of digits problem:
>>> ip = '192.168.1.1'
>>> print('%3s.%3s.%3s.%3s' % tuple(ip.split('.')))
192.168. 1. 1
>>> print('%s.%s.%s.%s' % tuple([s.zfill(3) for s in ip.split('.')]))
192.168.001.001
Example of sorting function
Well... Ferdinand Beyer in his answer seems to have already offered an excellent solution for this approach! :)
Found a solution at https://www.lesinskis.com/python_sorting_IP_addresses.html All you have to do is convert the string of ip in ipaddress
import ipaddress
sortedkey = sorted(list_of_ip_instring, key = ipaddress.IPv4Address)
You can use a custom key
function to return a sortable representation of your strings:
def split_ip(ip):
"""Split a IP address given as string into a 4-tuple of integers."""
return tuple(int(part) for part in ip.split('.'))
def my_key(item):
return split_ip(item[0])
items = sorted(ipCount.items(), key=my_key)
The split_ip()
function takes an IP address string like '192.168.102.105'
and turns it into a tuple of integers (192, 168, 102, 105)
. Python has built-in support to sort tuples lexicographically.
UPDATE: This can actually be done even easier using the inet_aton() function in the socket
module:
import socket
items = sorted(ipCount.items(), key=lambda item: socket.inet_aton(item[0]))
I think this will help you: PEP265 (sorting dictionieries by value). Just extend the sorted function.