Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Generating a "set of tuples" from a "list of tuples" that doesn't take order into consideration

If I have the list of tuples as the following:

[('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]

I would like to remove duplicate tuples (duplicate in terms of both content and order of items inside) so that the output would be:

[('a', 'b'), ('c', 'd')]

Or

[('b', 'a'), ('c', 'd')]

I tried converting it to set then to list but the output would maintain both ('b', 'a') and ('a', 'b') in the resulting set!

like image 289
Arabasta Avatar asked Dec 02 '15 20:12

Arabasta


2 Answers

Try this :

a = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]
b = list(set([ tuple(sorted(t)) for t in a ]))
[('a', 'b'), ('c', 'd')]

Let's break this down :

If you sort a tuple, it becomes a sorted list.

>>> t = ('b', 'a')
>>> sorted(t)
['a', 'b']

For each tuple t in a, sort it and convert it back to a tuple.

>>> b = [ tuple(sorted(t)) for t in a ]
>>> b
[('a', 'b'), ('c', 'd'), ('a', 'b'), ('a', 'b')]

Convert the resulting list b to a set : values are now unique. Convert it back to a list.

>>> list(set(b))
[('a', 'b'), ('c', 'd')]

Et voilà !

Note that you can skip the creation of the intermediate list b by using a generator instead of a list comprehension.

>>> list(set(tuple(sorted(t)) for t in a))
[('a', 'b'), ('c', 'd')]
like image 162
Eric Citaire Avatar answered Oct 18 '22 03:10

Eric Citaire


If you did not mind using a frozenset with a set:

l = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]

print(set(map(frozenset,l)))
{frozenset({'a', 'b'}), frozenset({'c', 'd'})}

You can convert back to tuple if preferable:

l = [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')]

print(list(map(tuple,set(map(frozenset ,l)))))
[('a', 'b'), ('d', 'c')]

Or using a set and reversing the order of the tuples:

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))
like image 43
Padraic Cunningham Avatar answered Oct 18 '22 03:10

Padraic Cunningham