Generate all combinations of positive and negative

Question:

I have this list of tuples

a = [(1, 2), (2, 1)]

And need all of the possible combinations of negative and positive:

b = [(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]

I’ve tried using itertools.product():

xs = list(product(*([[i, -j] for (i, j) in b])))
ys = list(product(*([[-i, j] for (i, j) in b])))
xs + ys

But it does not generate the correct numbers:

>>>xs + ys
[(1, 2), (1, -1), (-2, 2), (-2, -1), (-1, -2), (-1, 1), (2, -2), (2, 1)]
Asked By: SandWood Jones

||

Answers:

Code:

a = [(1, 2), (2, 1)]

res1=[]
for x in a:
    for i in [x[0], -x[0]]:
        for j in [x[1], -x[1]]:
            res1.append((i,j))

#Through list comprehension
res2=[(i,j) for x in a for i in [x[0],-x[0]] for j in [x[1],-x[1]]]

#Output
print(res1)
print(res2)

Output:

[(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]
[(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]

Using itertools

Code:

import itertools

a=[(1, 2), (2, 1)]

xs=list(itertools.product(*map(lambda x: (x, -x), a[0])))
ys=list(itertools.product(*map(lambda x: (x, -x), a[1])))

print(xs+ys) #Same output as above
Answered By: Yash Mehta
a = [(1, 2), (2, 1)]
b = []

for x, y in a:
    for i in [-1, 1]:
        for j in [-1, 1]:
            b.append((x*i, y*j))

print(b)
Answered By: user3327034

You should perform product on the signs instead:

[(sx * x, sy * y) for x, y in a for sx, sy in product((1, -1), repeat=2)]

You can also include a in a nested product:

[(sx * x, sy * y) for (x, y), (sx, sy) in product(a, product((1, -1), repeat=2))]

or map the sequences of numbers and signs to the multiplication operator:

from operator import mul

[tuple(map(mul, *t)) for t in product(a, product((1, -1), repeat=2))]

All three expressions would return:

[(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]

Demo: https://replit.com/@blhsing/DishonestShabbyUnix

Answered By: blhsing

(Note: currently the question is ambiguous. Once they clarify, I might have to update these.)

For tuples of any length:

[p for t in a for p in product(*((x, -x) for x in t))]

Or with operator.neg:

[p for t in a for p in product(*zip(t, map(neg, t)))]

Or without any Python looping, using chain/repeat/starmap from itertools (this is a direct conversion from the above solution):

[*chain(*starmap(product, map(zip, a, map(map, repeat(neg), a))))]

For tuples of length 2:

[(X, Y) for x, y in a for X in (x, -x) for Y in (y, -y)]
Answered By: Kelly Bundy

Here is the solution along the lines you are trying to solve…

xs = list(itertools.product(*([[(i),(-i)] for (i,j) in var_b])))

ys = list(itertools.product(*([[(j),(-j)] for (i,j) in var_b])))

print (xs + ys)

Output

[(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]
Answered By: IamSkSuresh