Reputation: 406
I am creating my own reporting tool, and I am trying to figure out how to sort IP address with port number.
How do I sort an IP address with port number such that I sort the IP address first and then through port number. I am able to sort IP address just fine, but when combining with port numbers, it becomes difficult.
a = ['192.168.0.3 (443/tcp)|', '192.168.0.176 (443/tcp)|', '192.168.0.40 (443/tcp)|', '192.168.0.15 (8443/tcp)|', '192.168.0.16 (8443/tcp)|', '192.168.0.12 (443/tcp)|', '192.168.0.9 (3389/tcp)|', '192.168.0.15 (443/tcp)|', '192.168.0.16 (443/tcp)|', '192.168.0.3 (3389/tcp)|', '192.168.0.14 (443/tcp)|']
print(a.sort(key=lambda s: map(int, s.split('.')))) #this works fine with just IP address not with the current format of (xxx/tcp). The pipe is for delimiters so please ignore.
I would like to get the output sorted by IP address first, and then for each IP to sort via port number. So for example, the first few results would be:
a= ['192.168.0.3 (443/tcp)|', '192.168.0.3 (3389/tcp)|', 192.168.0.9 (3389/tcp)|, ...']
Upvotes: 1
Views: 705
Reputation: 29742
Using re.findall
:
import re
def get_ip_port(x):
*ips, port = map(int, re.findall('\d+', x))
return ips, port
sorted(a, key=get_ip_port)
Output:
['192.168.0.3 (443/tcp)|',
'192.168.0.3 (3389/tcp)|',
'192.168.0.9 (3389/tcp)|',
'192.168.0.12 (443/tcp)|',
'192.168.0.14 (443/tcp)|',
'192.168.0.15 (443/tcp)|',
'192.168.0.15 (8443/tcp)|',
'192.168.0.16 (443/tcp)|',
'192.168.0.16 (8443/tcp)|',
'192.168.0.40 (443/tcp)|',
'192.168.0.176 (443/tcp)|']
Explanation:
map(int, re.findall('\d+', x))
: finds all digits and make them int
*ips, port
: unpacks the above int
s and repack into all but last one (*ips
) and last one (port
)sorted(a, key=get_ip_port)
: as get_ip_port
returns two keys (ips
,port
), sorted
sorts the a
first by ips
and then port
, just as desired.Upvotes: 4
Reputation: 12992
You can do it in just one line using sorted
like so:
sorted(a, key=lambda x:x.split(' ')[0])
Upvotes: 0
Reputation: 3787
You can sort with multiple criteria(with map(int,e[0].split('.'))
as criteria 1 and int(e[1].lstrip('(').split('/')[0])
as criteria2) as shown below,
>>> a
['192.168.0.3 (443/tcp)|',
'192.168.0.176 (443/tcp)|',
'192.168.0.40 (443/tcp)|',
'192.168.0.15 (8443/tcp)|',
'192.168.0.16 (8443/tcp)|',
'192.168.0.12 (443/tcp)|',
'192.168.0.9 (3389/tcp)|',
'192.168.0.15 (443/tcp)|',
'192.168.0.16 (443/tcp)|',
'192.168.0.3 (3389/tcp)|',
'192.168.0.14 (443/tcp)|']
>>> [i.split() for i in a]
[['192.168.0.3', '(443/tcp)|'],
['192.168.0.176', '(443/tcp)|'],
['192.168.0.40', '(443/tcp)|'],
['192.168.0.15', '(8443/tcp)|'],
['192.168.0.16', '(8443/tcp)|'],
['192.168.0.12', '(443/tcp)|'],
['192.168.0.9', '(3389/tcp)|'],
['192.168.0.15', '(443/tcp)|'],
['192.168.0.16', '(443/tcp)|'],
['192.168.0.3', '(3389/tcp)|'],
['192.168.0.14', '(443/tcp)|']]
>>> sorted([i.split() for i in a],key=lambda e: (map(int,e[0].split('.')),int(e[1].strip('(').split('/')[0])))
[['192.168.0.3', '(443/tcp)|'],
['192.168.0.3', '(3389/tcp)|'],
['192.168.0.9', '(3389/tcp)|'],
['192.168.0.12', '(443/tcp)|'],
['192.168.0.14', '(443/tcp)|'],
['192.168.0.15', '(443/tcp)|'],
['192.168.0.15', '(8443/tcp)|'],
['192.168.0.16', '(443/tcp)|'],
['192.168.0.16', '(8443/tcp)|'],
['192.168.0.40', '(443/tcp)|'],
['192.168.0.176', '(443/tcp)|']]
Upvotes: 0