从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')]