How to iterate few elements in Python arrays? - python

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.

Related

How to zip a list with a list of tuples?

Say I have the following lists:
list_a = [1, 4, 7]
list_b = [(2, 3), (5, 6), (8, 9)]
How do I combine them so that it becomes
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
You can expand the tuple in the second zipped item to build a final tuple
list_a = [1, 4, 7]
list_b = [(2, 3), (5, 6), (8, 9)]
print([(a,*b) for a,b in zip(list_a, list_b)])
Output
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
list_a = [1, 4, 7]
list_b = [(2, 3), (5, 6), (8, 9)]
# FOR LIST_A TO B
for i in range(len(list_a)):
a = list_a[i]
test = list_b[i] + (a,)
print(test)

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

generating tuples using n-lists with itertools.product

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)]
>>>

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