从Python列表中过滤掉“反向”重复的元组
问题内容:
我有一个这样的清单:
[('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')]
在具有更多类似的元组的情况下,此处的前两项只是相反顺序的IP地址。
现在,我需要创建一个新列表,该列表在每个元组中的两个第一个IP地址的组合上是唯一的。
也就是说,就我的目的而言('192.168.1.100', '192.168.1.101', 'A')
,与相同('192.168.1.101', '192.168.1.100', 'A')
,无论我最终获得那两个。虽然这些都不是一样的('192.168.1.101', '192.168.1.100', 'B')
给定开头的列表,我需要结束一个新列表:
[('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')]
用python做到这一点的优雅方法是什么?
问题答案:
简单但效率低下的(O(n²)
)方法(感谢@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')]
使用Python的更有效的方法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')]
您可以根据最后一个元素对其进行排序:
>>> 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')]