generating tuples using n-lists with itertools.product - python

How can I use itertools.product function if I don't know the number of the lists? I have list and it has lists inside of it.
Like,
lis = [[1,2,3],[6,7,8],[2,4,5]]
Normally I need to do,
product([1,2,3],[6,7,8],[2,4,5])
How do I do that if the input is a list like in the example?

Try the following:
product(*lis)
It's called argument unpacking.
Short note: you can use argument unpacking with named parameters also, with double star:
def simpleSum(a=1,b=2):
return a + b
simpleSum(**{'a':1,'b':2}) # returns 3

Use argument unpacking:
>>> lis = [[1,2,3],[6,7,8],[2,4,5]]
>>> list(itertools.product(*lis))
[(1, 6, 2), (1, 6, 4), (1, 6, 5), (1, 7, 2), (1, 7, 4), (1, 7, 5), (1, 8, 2),
(1, 8, 4), (1, 8, 5), (2, 6, 2), (2, 6, 4), (2, 6, 5), (2, 7, 2), (2, 7, 4),
(2, 7, 5), (2, 8, 2), (2, 8, 4), (2, 8, 5), (3, 6, 2), (3, 6, 4), (3, 6, 5),
(3, 7, 2), (3, 7, 4), (3, 7, 5), (3, 8, 2), (3, 8, 4), (3, 8, 5)]
>>>

Related

How to make couple for elements from two list (different size) in Python?

I need to make couple for elements from two lists (two lists are different size)
Ex:
x = ([3,2], [4,6,-8])
y = ([-5,1,4], [13,9], [7,5,-1,10])
Result:
new_list = ([3, -5], [3, 1], [3, 4], [3, 13], [3, 9], [3, 7], [3, 5], [3, -1],[3, 10], [2, -5], [2, 1] ......<sorry, there're too many>.... [-8, 5], [-8, -1], [-8, 10])
Thanks for support!
In two steps, 1) flatten your list of lists, 2) itertools.product
Flatten your list of lists:
How to make a flat list out of a list of lists
flat_list = itertools.chain(*iterable_of_lists)
Use itertools to create the product of the two lists.
itertools.product(x, y)
Example from OP:
import itertools
x = ([3,2], [4,6,-8])
y = ([-5,1,4], [13,9], [7,5,-1,10])
x_flat = itertools.chain(*x)
y_flat = itertools.chain(*y)
list(itertools.product(x_flat, y_flat))
result:
[(3, -5), (3, 1), (3, 4), (3, 13), (3, 9), (3, 7), (3, 5), (3, -1), (3, 10), (2, -5), (2, 1), (2, 4), (2, 13), (2, 9), (2, 7), (2, 5), (2, -1), (2, 10), (4, -5), (4, 1), (4, 4), (4, 13), (4, 9), (4, 7), (4, 5), (4, -1), (4, 10), (6, -5), (6, 1), (6, 4), (6, 13), (6, 9), (6, 7), (6, 5), (6, -1), (6, 10), (-8, -5), (-8, 1), (-8, 4), (-8, 13), (-8, 9), (-8, 7), (-8, 5), (-8, -1), (-8, 10)]
Your x, y and new_list in the examples are actually tuples and not lists, because you use () instead of [].
Based on your expected result, I assume that you don't really need lists of lists here, you just take flat lists:
x = [3,2,4,6,-8]
y = [-5,1,4,13,9,7,5,-1,10]
And find each combination between x and y. Which can be done using itertools.product
Using itertools chain and product:
from itertools import product, chain
new_list = list(product(chain(*x), chain(*y)))
[(3, -5), (3, 1), (3, 4), (3, 13), (3, 9), (3, 7), (3, 5), (3, -1), (3, 10), (2, -5), (2, 1), (2, 4), (2, 13), (2, 9), (2, 7), (2, 5), (2, -1), (2, 10), (4, -5), (4, 1), (4, 4), (4, 13), (4, 9), (4, 7), (4, 5), (4, -1), (4, 10), (6, -5), (6, 1), (6, 4), (6, 13), (6, 9), (6, 7), (6, 5), (6, -1), (6, 10), (-8, -5), (-8, 1), (-8, 4), (-8, 13), (-8, 9), (-8, 7), (-8, 5), (-8, -1), (-8, 10)]
First of all you have two tuples containing lists, not lists of numbers and the expected result is a tuple containing two-length lists. So, you have to convert those tuples of lists to simple tuples first, following this solution (with a little change): https://stackoverflow.com/a/952952/11882999
x = ([3,2], [4,6,-8])
y = ([-5,1,4], [13,9], [7,5,-1,10])
x_tuple = tuple(item for sublist in x for item in sublist)
y_tuple = tuple(item for sublist in y for item in sublist)
Then following this solution (with a little change), you can calculate the combinations of two tuples easily: https://stackoverflow.com/a/39064769/11882999
result = tuple([x, y] for x in x_tuple for y in y_tuple)
>> ([3, -5], [3, 1], [3, 4], ..., [-8, 5], [-8, -1], [-8, 10])

Backtracking to create squares

a = []
def make_squares(arr, length, nums):
if not nums:
print(arr)
a.append(arr)
return
r = 0
while r < len(arr) and len(arr[r]) == length:
r += 1
for i in nums:
nums.remove(i)
arr[r].append(i)
make_squares(arr, length, nums)
nums.append(i)
arr[r] = arr[r][:-1]
make_squares([[] for i in range(3)], 3, [i+1 for i in range(3**2)])
print(a)
I'm trying to use the above code to create nxn matrices each with a permutation of the numbers i+1...n^2. I have printed every matrix that gets appended to a and they appear correct, but when I print a in the end, I get [[[], [], []], [[], [], []], ...]. It doesn't make any sense to me.
The expected result would be
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[1, 2, 3], [4, 5, 6], [7, 9, 8]], ...]
The order may not be the same as in your expected result, but this does the trick with the standard library itertools module:
import itertools
def make_squares(w):
size = w * w
for perm in itertools.permutations(range(1, size + 1)):
# "grouper" from the itertools recipe list
yield list(itertools.zip_longest(*[iter(perm)] * w))
for square in make_squares(3):
print(square)
prints
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
[(1, 2, 3), (4, 5, 6), (7, 9, 8)]
[(1, 2, 3), (4, 5, 6), (8, 7, 9)]
[(1, 2, 3), (4, 5, 6), (8, 9, 7)]
[(1, 2, 3), (4, 5, 6), (9, 7, 8)]
[(1, 2, 3), (4, 5, 6), (9, 8, 7)]
[(1, 2, 3), (4, 5, 7), (6, 8, 9)]
[(1, 2, 3), (4, 5, 7), (6, 9, 8)]
[(1, 2, 3), (4, 5, 7), (8, 6, 9)]
[(1, 2, 3), (4, 5, 7), (8, 9, 6)]
[(1, 2, 3), (4, 5, 7), (9, 6, 8)]
[(1, 2, 3), (4, 5, 7), (9, 8, 6)]
[(1, 2, 3), (4, 5, 8), (6, 7, 9)]
[(1, 2, 3), (4, 5, 8), (6, 9, 7)]
[(1, 2, 3), (4, 5, 8), (7, 6, 9)]
...

Creating specific permutations Python

I have values for a 2-dimensional list:
# 4 x 4, 2-dimensional list
values = [[4, 7, 8],
[1, 3, 4],
[7, 5, 6],
[2, 9, 1]]
I want to create tuples containing all possible permutations of these values (Cartesian product) for each list.
# example for the list at index 0 of values
args0 = [(4, 7, 8), (7, 4, 8), (4, 8, 7), (8, 4, 7), (7, 8, 4), (8, 7, 4)]
Is there an easy way to go about this? I have tried itertools but cannot get it to work with "specific values".
What you want is the permutations of each element in the list, so just map itertools.permutations:
import itertools
values = [[4, 7, 8],
[1, 3, 4],
[7, 5, 6],
[2, 9, 1]]
perms = map(itertools.permutations, values)
for v in perms:
print(list(v))
Result:
[(4, 7, 8), (4, 8, 7), (7, 4, 8), (7, 8, 4), (8, 4, 7), (8, 7, 4)]
[(1, 3, 4), (1, 4, 3), (3, 1, 4), (3, 4, 1), (4, 1, 3), (4, 3, 1)]
[(7, 5, 6), (7, 6, 5), (5, 7, 6), (5, 6, 7), (6, 7, 5), (6, 5, 7)]
[(2, 9, 1), (2, 1, 9), (9, 2, 1), (9, 1, 2), (1, 2, 9), (1, 9, 2)]
Here you have a live example

How to iterate few elements in Python arrays?

For example I have a list of objects like this:
[[{1},{2},{3}],[{4},{5}],[{6},{7},{8}]]
I need to iterate through them all to get on each iteration objects like:
1,4,6
1,4,7
1,4,8
1,5,6
1,5,7
1,5,8
2,4,6
2,4,7
2,4,8
2,5,6
2,5,7
2,5,8
Basically each result is like a sub array of the input lists.
You can easily use itertools.product
>>> import itertools
>>> x = list(itertools.product([1,2,3],[4,5],[6,7,8]))
[(1, 4, 6), (1, 4, 7), (1, 4, 8), (1, 5, 6), (1, 5, 7), (1, 5, 8), (2, 4, 6), (2, 4, 7), (2, 4, 8), (2, 5, 6), (2, 5, 7), (2, 5, 8), (3, 4, 6), (3, 4, 7), (3, 4, 8), (3, 5, 6), (3, 5, 7), (3, 5, 8)]
Note that the output of every combination you are looking for is called the Cartesian product of your input lists.

get adjacent matrix of point in python

If in 2D, p(x,y), I'd like to have a adjacent matrix of 3*3:
(x-1,y-1), (x,y-1), (x+1,y-1),
...
(x-1,y+1), (x,y+1), (x+1,y+1),
What if in 3D(3*3*3), 4D(3*3*3*3),...?
Is there better function?
You might also be able to use itertools.product, depending on exactly what output format you prefer. It'll be slower than a numpy approach but I find it easier to understand:
from itertools import product
def adjacent_grid(centre):
steps = product([-1, 0, 1], repeat=len(centre))
return (tuple(c+d for c,d in zip(centre, delta)) for delta in steps)
which gives
>>> list(adjacent_grid((3,)))
[(2,), (3,), (4,)]
>>> list(adjacent_grid((3,3)))
[(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2), (4, 3), (4, 4)]
>>> list(adjacent_grid((3,3,3)))
[(2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 2), (2, 3, 3), (2, 3, 4), (2, 4, 2), (2, 4, 3), (2, 4, 4), (3, 2, 2), (3, 2, 3), (3, 2, 4), (3, 3, 2), (3, 3, 3), (3, 3, 4), (3, 4, 2), (3, 4, 3), (3, 4, 4), (4, 2, 2), (4, 2, 3), (4, 2, 4), (4, 3, 2), (4, 3, 3), (4, 3, 4), (4, 4, 2), (4, 4, 3), (4, 4, 4)]
You can get the result by using broadcasting in numpy:
import numpy as np
def p(*args):
args = np.array(args)
idx = np.array([-1, 0, 1])
a = np.broadcast_arrays(*np.ix_(*(args[:,None] + idx)))
return np.concatenate([x[..., None] for x in a], axis=-1)
The result shape is (3,3,2) in 2D, (3,3,3,3) in 3D, (3,3,3,3,4) in 4D:
>>> p(3, 8)
array([[[2, 7],
[2, 8],
[2, 9]],
[[3, 7],
[3, 8],
[3, 9]],
[[4, 7],
[4, 8],
[4, 9]]])

Categories

Resources