xyhuang
xyhuang

Reputation: 424

How to generate itertools product without duplicates and symmetric?

I know there is a very similar question: Itertools product without repeating duplicates

but I have something different. For example:

a = ['add', 'sub']
b = [2,3, 'a', 'b']
c = [1,3, 'a', 'c']
list(it.product(a, b, c))  # result is:[('add', 2, 1),('add', 2, 3),('add', 2, 'a'), ('add', 2, 'c'),
#('add', 3, 1),('add', 3, 3),('add', 3, 'a'),('add', 3, 'c'),('add', 'a', 1),('add', 'a', 3),
#('add', 'a', 'a'),('add', 'a', 'c'), ('add', 'b', 1),('add', 'b', 3),('add', 'b', 'a'),
#('add', 'b', 'c'),('sub', 2, 1),('sub', 2, 3),('sub', 2, 'a'),('sub', 2, 'c'),('sub', 3, 1),
#('sub', 3, 3),('sub', 3, 'a'),('sub', 3, 'c'),('sub', 'a', 1),('sub', 'a', 3),('sub', 'a', 'a'),
#('sub', 'a', 'c'),('sub', 'b', 1),('sub', 'b', 3),('sub', 'b', 'a'),('sub', 'b', 'c')]

for the result:

I don't want add(a,a), as the first value == second value.

I want to keep only 1 of add(3,a), add(a,3), as it is symmetric.

and my example only contains two list, but I may use 5 or more lists to generate product.

I cant use combinations, because:

product(['add', 'sub', 1,2,3, 'a','b', 'c'], repeat=3) is different with product(['add', 'sub'], [2,3, 'a', 'b'], [1,3, 'a', 'c'])

Something in product(['add', 'sub', 1,2,3, 'a','b', 'c'], repeat=3) is not ok for me.

I want a fast method, since my program is time sensitive.

Upvotes: 0

Views: 526

Answers (1)

Dani Mesejo
Dani Mesejo

Reputation: 61910

IIUC, you could do:

from itertools import product, combinations, chain

a = ['add', 'sub']
b = [2, 3, 'a', 'b']
c = [1, 3, 'a', 'c']

for operation, operands in product(a, combinations(set(chain(b, c)), r=2)):
    print((operation, *operands))

Output

('add', 1, 2)
('add', 1, 3)
('add', 1, 'a')
('add', 1, 'b')
('add', 1, 'c')
('add', 2, 3)
('add', 2, 'a')
('add', 2, 'b')
('add', 2, 'c')
('add', 3, 'a')
('add', 3, 'b')
('add', 3, 'c')
('add', 'a', 'b')
('add', 'a', 'c')
('add', 'b', 'c')
('sub', 1, 2)
('sub', 1, 3)
('sub', 1, 'a')
('sub', 1, 'b')
('sub', 1, 'c')
('sub', 2, 3)
('sub', 2, 'a')
('sub', 2, 'b')
('sub', 2, 'c')
('sub', 3, 'a')
('sub', 3, 'b')
('sub', 3, 'c')
('sub', 'a', 'b')
('sub', 'a', 'c')
('sub', 'b', 'c')

Upvotes: 2

Related Questions