2011-07-01 36 views
10

我有一段代码,看起来像这样:如何在Python中对字典中存储的IP地址进行排序?

ipCount = defaultdict(int) 

for logLine in logLines: 
    date, serverIp, clientIp = logLine.split(" ") 
    ipCount[clientIp] += 1 

for clientIp, hitCount in sorted(ipCount.items), key=operator.itemgetter(0)): 
    print(clientIp) 

和它种排序IP的,但像这样:

192.168.102.105 
192.168.204.111 
192.168.99.11 

这是不够的,因为它不承认99是采用小于102或204,我想输出是这样的:

192.168.99.11 
192.168.102.105 
192.168.204.111 

我发现this,但我不知道如何IMPL在我的代码中使用它,或者如果它甚至可能是因为我使用了字典。我在这里有什么选择?谢谢..

回答

24

您可以使用自定义key函数返回弦的排序表示:

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) 

split_ip()功能需要一个IP地址字符串像'192.168.102.105'并将其转化为整数(192, 168, 102, 105)的元组。 Python具有内置的支持,可按字典顺序对元组进行排序。

UPDATE:这实际上可以使用inet_aton()功能socket模块中完成更简单:

import socket 
items = sorted(ipCount.items(), key=lambda item: socket.inet_aton(item[0])) 
+0

你也可以用'map'功能做到这一点:'排序(ipCount.items(),键=拉姆达X:元组(图(INT,x.split())“”)))' – Handyman5

+0

我看到使用INET_ATON更新的答案是不同的:鲁的电话struct.unpack和费迪南德的没有。这个函数调用是否需要订购? –

+0

@randomtoor:*不*必须。 'inet_aton'返回一个4个字符的字符串,Python知道如何比较和排序字符串。 –

2

我在这里有什么选择?

两个明显的一个来我的脑海中:

  1. 的预格式化字符串与IP当您将它们保存从你把你的问题的链接。
  2. 当您执行排序时,传递排序功能sorted()函数。

哪一个是最好从数据量取决于你必须处理和你将需要说做什么(你会只针对数据量非常大的发现为方法#1的性能提高)排序后的IP列表(如果您预先格式化了字符串,则可能需要在将它们作为参数提供给其他函数之前再次进行更改)。

实施例预格式化

维护IP作为字符串,但使用空格或零解决可变号码数字的问题:

>>> 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 

排序功能

的实施例

好吧......费迪南德拜尔在his answer似乎已经提供了一个很好的解决方案,这种方法!:)

10

使用的排序的关键参数,你的ip转换为整数,例如:

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)) 

编辑:

Gryphius提出与插座模块的解决方案,所以为什么不使用它使长期从IP转换,因为它是清洁:

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]) 
1

我认为这将有助于您:PEP265(按价值排序dictionieries)。只要扩展排序的功能。

2

,如果你的应用程序做大量的事情,如“在范围X找到IPS”,“排序IP”等其往往更便捷的存储的ip数值内部以及与这一个工作。

from socket import inet_aton,inet_ntoa 
import struct 

def ip2long(ip): 
    packed = inet_aton(ip) 
    lng = struct.unpack("!L", packed)[0] 
    return lng 

转换为数字回一个IP使用此功能:

def long2ip(lng): 
    packed = struct.pack("!L", lng) 
    ip=inet_ntoa(packed) 
    return ip 


>>> ip2long('192.168.1.1') 
3232235777 
>>> ip2long('1.2.3.4') 
16909060 
>>> long2ip(3232235777) 
'192.168.1.1' 
>>> long2ip(16909060) 
'1.2.3.4' 
+0

+1,用于推荐'socket'模块。但是由于问题是关于排序问题,所以您可能想要举一个例子来说明如何在这种情况下使用它。 –

+0

sixfeetsix刚刚做到了:-) – Gryphius

+0

是的,我也是;) –

相关问题