I've a list like this:
[('192.168.1.100', '192.168.1.101', 'A'), ('192.168.1.101', '192.168.1.100', 'A'),
('192.168.1.103', '192.168.1.101', 'B'), ('192.168.1.104', '192.168.1.100', 'C')]
And with many more similar tuples, here the two first items are just the IP addresses in the opposite order.
Now, I need to create a new list which is unique on the combination of the 2 first IP addresses in each tuple.
That is, for my purpose ('192.168.1.100', '192.168.1.101', 'A')
is the same as ('192.168.1.101', '192.168.1.100', 'A')
, it doesn't matter which of those 2 I end up with. Though none of those would be the same as ('192.168.1.101', '192.168.1.100', 'B')
Given the list at the start, I need to end up with a new list:
[('192.168.1.101', '192.168.1.100', 'A'), ('192.168.1.103', '192.168.1.101', 'B'),
('192.168.1.104', '192.168.1.100', 'A')]
What's an elegant way of doing this in python ?
The straightforward, yet inefficient (O(n²)
) approach (thanks, @Rafał Dowgird!):
>>> uniq=[]
>>> for i in l: # O(n), n being the size of l
... if not (i in uniq or tuple([i[1], i[0], i[2]]) in uniq): # O(n)
... uniq.append(i) # O(1)
...
>>> uniq
[('192.168.1.100', '192.168.1.101', 'A'),
('192.168.1.103', '192.168.1.101', 'B'),
('192.168.1.104', '192.168.1.100', 'C')]
A more efficient approach using Python's Set
:
>>> uniq=set()
>>> for i in l: # O(n), n=|l|
... if not (i in uniq or tuple([i[1], i[0], i[2]]) in uniq): # O(1)-Hashtable
... uniq.add(i)
...
>>> list(uniq)
[('192.168.1.104', '192.168.1.100', 'C'),
('192.168.1.100', '192.168.1.101', 'A'),
('192.168.1.103', '192.168.1.101', 'B')]
You can sort it according to the last element:
>>> sorted(list(uniq), key=lambda i:i[2])
[('192.168.1.100', '192.168.1.101', 'A'),
('192.168.1.103', '192.168.1.101', 'B'),
('192.168.1.104', '192.168.1.100', 'C')]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With