Cartesian Product of Sets where No Elements are Id

2020-05-08 12:20发布

I have some sets I would like to take the Cartesian product of, which is working well. However, I want to remove all elements of this new set which are identical under a permutation of the elements.

For example, take the following code:

import itertools as ittools
x = 2
y = 3
z = 5

flist = list(ittools.product([x,y,z],repeat=3))

for f in flist:
    print reduce(lambda a,b: a*b, f)

This code find the Cartesian product of the set {2,3,5} and returns the product of all three components of each element in the resulting set. However, some numbers appear multiple times, i.e. 12 can be written as 2*2*3, 2*3*2, or 3*2*2. I would like to remove all but one instance of these duplicates.

I know that this fundamentally a combinatorics problem, but this seems like there is probably a nice solution in Python that doesn't involve doing an extra pass over the list like I did here to compute some identifier for each element of the Cartesian product.

2条回答
倾城 Initia
2楼-- · 2020-05-08 13:12

Use a dict to map each unique product to the most recently seen tuple.

d = {reduce(operator.mul, f): f for f in flist}

If you would need to treat tuples that aren't permutations of each other as distinct elements, you'll need a more complicated key that incorporates a canonical representation of the tuple.

from operator import mul
d = {(tuple(sorted(f)), reduce(mul, f)): f for f in flist}

Actually, once you do that, you don't need to map the tuple/product pair to a tuple; you can just maintain a set of pairs:

d = {(tuple(sorted(f)), reduce(mul, f)) for f in flist}

In any case, retrieving just the tuples is as simple as

tuples = d.values()  # In the first two cases
tuples = {x for x,y in d} # In the third case
查看更多
Lonely孤独者°
3楼-- · 2020-05-08 13:13

You want combinations_with_replacement, not product:

itertools.combinations_with_replacement([x, y, z], 3)
查看更多
登录 后发表回答