如果我有如下元组列表:
[('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
我想删除重复的元组(在内容和内部项目顺序方面都是重复的(,以便输出为:
[('a', 'b'), ('c', 'd')]
或
[('b', 'a'), ('c', 'd')]
我尝试将其转换为 set 然后转换为列表,但输出将在结果集中保持('b', 'a')
和('a', 'b')
!
试试这个:
a = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
b = list(set([ tuple(sorted(t)) for t in a ]))
[('a', 'b'), ('c', 'd')]
让我们分解一下:
如果对元组进行排序,它将变为排序列表。
>>> t = ('b', 'a')
>>> sorted(t)
['a', 'b']
对于a
中的每个元组t
,对其进行排序并将其转换回元组。
>>> b = [ tuple(sorted(t)) for t in a ]
>>> b
[('a', 'b'), ('c', 'd'), ('a', 'b'), ('a', 'b')]
将结果列表b
转换为集合:值现在是唯一的。将其转换回列表。
>>> list(set(b))
[('a', 'b'), ('c', 'd')]
瞧!
请注意,您可以使用生成器而不是列表推导式跳过中间列表b
的创建。
>>> list(set(tuple(sorted(t)) for t in a))
[('a', 'b'), ('c', 'd')]
如果您不介意将冻结集与集合一起使用:
l = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
print(set(map(frozenset,l)))
{frozenset({'a', 'b'}), frozenset({'c', 'd'})}
如果愿意,您可以转换回元组:
l = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
print(list(map(tuple,set(map(frozenset ,l)))))
[('a', 'b'), ('d', 'c')]
或者使用集合并反转元组的顺序:
l = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
seen, pairs = set(), []
for a,b in l:
if (a,b) not in seen and (b,a) not in seen:
pairs.append((a,b))
seen.add((a,b))
如果顺序不重要,这可以解决您的问题。
a=[('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
a=map(tuple,[sorted(i) for i in a])
print list(set(a))
输出:
[('a', 'b'), ('c', 'd')]
只是想添加一个潜在的第二个解决方案,如果有人有一个"先到先得"可能很重要的用例。
例如,假设我们获取三个列表并将它们合并到一个元组列表中:
# Make some lists (must be same size)
a = [1,1,1,2,8,6,1]
b = [2,4,6,1,4,21,69]
c = [2,8,21,2,1,1,8]
# Lists to list of tuples
arr = []
for i in range(len(a)):
new_row = (a[i],b[i],c[i])
arr.append(new_row)
这样我们的原始数组看起来像:
(1, 2, 2)
(1, 4, 8)
(1, 6, 21)
(2, 1, 2)
(8, 4, 1)
(6, 21, 1)
(1, 69, 8)
在我们的例子中,我们希望删除像 (2,1,2( 和 (8,4,1( 这样的项目,因为它们><分别等同于 和=" filtered
=" />首先,我们检查每个项目的排列是否存在于filtered
列表中.
如果没有,我们添加。如果是,我们跳过重复项。
filtered = []
for i in range(len(arr)):
it = itertools.permutations(arr[i])
perms = []
for p in it:
perms.append(p)
check = any(item in perms for item in filtered)
if not check:
filtered.append(arr[i])
现在,如果我们遍历filtered
并打印,我们会看到截断的元组列表:
(1, 2, 2)
(1, 4, 8)
(1, 6, 21)
(1, 69, 8)
请注意,我们只剩下每个数字元组的第一个实例,并且不通过set
工作可以保证在迭代过滤列表时元素的顺序相同。
我唯一不是100%的就是这样做的时间/空间复杂性 - 如果有人有反馈,我很想听听。
内置类型来救援:
data = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
set(map(frozenset, data))
{frozenset({'a', 'b'}), frozenset({'c', 'd'})}