2011-07-01 41 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

是的,我也是;) –

相關問題