Alex
Alex

Reputation: 2040

Get all unique combinations from list of permutations

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

Answers (3)

Gil Hamilton
Gil Hamilton

Reputation: 12357

One step further simplified (dropping map):

new = {tuple(sorted(n)) for n in X}

Upvotes: 1

RemcoGerlich
RemcoGerlich

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

Kasravnd
Kasravnd

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

Related Questions