Reputation: 2040
TL/DR
Given X = {(A,B),(B,C),(D,E),(B,A),(C,B)}
(where X
is a set
)
How do I filter for the subtuples which show a unique combination (instead of a unique permutation) such that X
becomes
{(A,B),(B,C),(D,E))}
Longer form
Somewhat of an inverse problem from most of the combination/permutation questions on here.
I have a set of tuples (outer tuples), where each tuple has 2 elements, both of which are also tuples (inner tuples), and each sub-tuple has two elements, both of which are integers.
As an example, the set with three elements might look like
X = { ( (1,2),(2,3) ), ( (1,3),(1,2) ), ( (2,3),(1,2) ) }
While all the outer tuples are unique, I'd like to build a subset which contains the set of unqiue tuples where the ORDER of the two inner tuples is irrelevant (i.e. a set of unique combinations). In the example above this would reduce to;
X = { ( (1,2),(2,3) ), ( (1,3),(1,2) )}
Because
( (1, 2),(2,3) ) and ( (2,3),(1,2) ) )
are both just combinations of (1, 2)
and (2,3)
.
There are obvious brute-force/for-loop approaches to this but they don't feel very Pythonic.
Maybe leveraging itertools
and map
?
Upvotes: 2
Views: 1627
Reputation: 12357
One step further simplified (dropping map):
new = {tuple(sorted(n)) for n in X}
Upvotes: 1
Reputation: 31270
One way would be to sort the tuples, then make a new set. (A, B) and (B, A) will both have been sorted to (A, B), and thus only occur once.
def to_sorted(t):
return tuple(sorted(t))
Xnew = {to_sorted(t) for t in X}
Another is to not use tuples at all -- tuples are ordered, and you don't care about the order. You could use sets. frozensets are immutable sets that can be elements of other sets:
Xnew = {frozenset(t) for t in X}
I like this slightly better, but 1) it doesn't work if your tuples contain multiples, and 2) now you have frozensets instead of tuples, your other code probably needs changing.
Upvotes: 2
Reputation: 107347
You can apply the sorted
function on your elements using map
and then use a set comprehension to get the unique elements :
>>> new={tuple(i) for i in map(sorted,X)}
>>> new
set([('B', 'C'), ('A', 'B'), ('D', 'E')])
But note that since sorted
convert your elements to list you need to reverse them to tuple
because lists are not hashable.
Upvotes: 2