Numpy: reshape list of tuples - python

I have the following list of tuples:
>>> import itertools
>>> import numpy as np
>>> grid = list(itertools.product((1,2,3),repeat=2))
>>> grid
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
I'd like to reshape this list in a sensible way (e.g. using numpy if possible) to be 3x3 as follows:
[[(1, 1), (1, 2), (1, 3)],
[(2, 1), (2, 2), (2, 3)],
[(3, 1), (3, 2), (3, 3)]]
When I do np.reshape(grid, (3, 3)) I get the following error: ValueError: cannot reshape array of size 18 into shape (3,3) (size 18??)
I've tried variations of np.reshape(grid, (3, 3, 2)) but these don't return the 3x3 grid given above.

This will do the job:
new_grid = np.empty(len(grid), dtype='object')
new_grid[:] = grid
new_grid = new_grid.reshape(3, 3)
This outputs:
array([[(1, 1), (1, 2), (1, 3)],
[(2, 1), (2, 2), (2, 3)],
[(3, 1), (3, 2), (3, 3)]], dtype=object)
The object type will remain tuple:
type(new_grid[0, 0])
tuple

18 comes from the fact that you have a list of 9 tuples, each containing 2 items; thus, 9 * 2 = 18. numpy automatically converts the tuples to part of the array.
You can either use LeonardoVaz's answer or do it speedily with nested list comprehension:
reshaped_grid = [[grid[i+j] for j in range(3)] for i in range(0, len(grid), 3)]
Output:
>>> reshaped_grid
[
[(1, 1), (1, 2), (1, 3)],
[(2, 1), (2, 2), (2, 3)],
[(3, 1), (3, 2), (3, 3)]
]

Related

How to select spesific list from nested lists with python [duplicate]

This question already has answers here:
Pythonic way of checking if a condition holds for any element of a list
(3 answers)
Apply function to each element of a list
(4 answers)
Closed 9 months ago.
Hello guys I have list like A
max_x=4
min_x=0
A=[[(0, 1), (1, 0), (1, 1), (2, 0)], [(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]]
A, includes different group of points (x,y) format.I wanted to find group if includes my max and min same time.Output should be like B.Because this cluster includes 0 and 4 as x.
B= [(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]
Thank you.
You could use a list comprehension to find any sublists of A that have a tuple that has x == min_x and also a tuple that has x == max_x:
max_x=4
min_x=0
A=[[(0, 1), (1, 0), (1, 1), (2, 0)], [(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]]
B = [l for l in A if any(x == min_x for x,_ in l) and any(x == max_x for x,_ in l)]
Output:
[[(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]]

Product of coordinates with specific order of iteration

Here's a snippet with a regular itertools.product usage:
from itertools import product
arr = [1,2,3]
pairs = list(product(arr, arr))
# pairs = [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
Now I would like to have these points yielded in an order which can be achieved by sorting the resulting tuples in the following way:
sorted(pairs, key=lambda y:max(y))
# [(1, 1), (1, 2), (2, 1), (2, 2), (1, 3), (2, 3), (3, 1), (3, 2), (3, 3)]
Is there a way for me to input those numbers to itertools.product so it yields the tuples in this order, or do I need to sort the pairs after iterating over the results of itertools.product?
You can probably use your own modified approach to achieve this in one go.
sorted([(x, y) for x in [1, 2, 3] for y in [1, 2, 3]], key=lambda y:max(y))
OUTPUT
[(1, 1), (1, 2), (2, 1), (2, 2), (1, 3), (2, 3), (3, 1), (3, 2), (3, 3)]

find combinations in arbitrarily nested lists under conditions

I want to find possible paths on a finite grid of points. Say, starting point is (x,y). Then next point (m,n) in the path is given by conditions
(m!=x) and (n!=y) ie. I exclude the row and column I was in previously.
n < y ie. I always hop DOWN.
m,n >= 0 ie. all the points are always in first quadrant
Stopping criteria is when a point lies on x axis.
Hence, generate all possible combinations of such 'paths' possible.
Following is what I've tried.
def lisy(x,y):
return [(i,j) for i in range(4,0,-1) for j in range(4,0,-1) if(i!=x and j<y)]
def recurse(x,y):
if (not lisy(x,y)):
return (x,y)
else:
return [(x,y), [recurse(i,j) for i,j in lisy(x,y)]]
OUTPUT:
In [89]: recurse(1,4)
Out[89]:
[(1, 4),
[[(4, 3),
[[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(3, 3),
[[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(2, 3),
[[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1)]]
This gives me a nested lists of possible new points from each point.
Can anyone tell me how to process my list obtained from recurse(1,4)?
edit1:
Effectively I hop from a given starting point (in a 4x4 grid [finite]), satisfying the three conditions mentioned until stopping criteria is met, ie. m,n > 0
I clarify the requirements I am working under in the docstring of my generator gridpaths(). Note that I have the horizontal size of the grid as a global variable and the vertical size of the grid is irrelevant, the x-coordinates of path points can be up to but not exceed that global value, and x-coordinates of non-consecutive path points can be equal (though consecutive path points must have different x-coordinates). I changed the name of the routine but kept the arguments as you had them. This version of my code adds the requirement that the y-coordinate of the final point on the path must be 1, and it also is safer in accepting arguments.
This is a generator of lists, so my test code shows how large the generator is then prints all the lists.
def gridpaths(x, y):
"""Generate all paths starting at (x,y) [x and y must be positive
integers] where, if (m,n) is the next point in the path after
(x,y), then m and n are positive integers, m <= xsize [xsize is a
global variable], m != x, and n < y, and so on for all consecutive
path points. The final point in the path must have a y-coordinate
of 1. Paths are yielded in lexicographic order."""
def allgridpaths(x, y, pathsofar):
"""Generate all such paths continuing from pathssofar without
the y == 1 requirement for the final path point."""
newpath = pathsofar + [(x, y)]
yield newpath
for m in range(1, xsize+1):
if m != x:
for n in range(1, y):
for path in allgridpaths(m, n, newpath):
yield path
x, y = max(int(x), 1), max(int(y), 1) # force positive integers
for path in allgridpaths(x, y, []):
# Only yield paths that end at y == 1
if path[-1][1] == 1:
yield path
# global variable: horizontal size of grid
xsize = 4
print(sum(1 for p in gridpaths(1, 4)), 'paths total.')
for p in gridpaths(1, 4):
print(p)
The printout shows that the point (1,4) in a 4x4 grid yields 48 paths. In fact, gridpaths(x, y) will return (xsize - 1) * xsize ** (y - 2) paths, which can grow very quickly. That is why I programmed a generator of lists rather than a list of lists. Let me know if your requirements are different from what I suppose. The printout from that code above is:
48 paths total.
[(1, 4), (2, 1)]
[(1, 4), (2, 2), (1, 1)]
[(1, 4), (2, 2), (3, 1)]
[(1, 4), (2, 2), (4, 1)]
[(1, 4), (2, 3), (1, 1)]
[(1, 4), (2, 3), (1, 2), (2, 1)]
[(1, 4), (2, 3), (1, 2), (3, 1)]
[(1, 4), (2, 3), (1, 2), (4, 1)]
[(1, 4), (2, 3), (3, 1)]
[(1, 4), (2, 3), (3, 2), (1, 1)]
[(1, 4), (2, 3), (3, 2), (2, 1)]
[(1, 4), (2, 3), (3, 2), (4, 1)]
[(1, 4), (2, 3), (4, 1)]
[(1, 4), (2, 3), (4, 2), (1, 1)]
[(1, 4), (2, 3), (4, 2), (2, 1)]
[(1, 4), (2, 3), (4, 2), (3, 1)]
[(1, 4), (3, 1)]
[(1, 4), (3, 2), (1, 1)]
[(1, 4), (3, 2), (2, 1)]
[(1, 4), (3, 2), (4, 1)]
[(1, 4), (3, 3), (1, 1)]
[(1, 4), (3, 3), (1, 2), (2, 1)]
[(1, 4), (3, 3), (1, 2), (3, 1)]
[(1, 4), (3, 3), (1, 2), (4, 1)]
[(1, 4), (3, 3), (2, 1)]
[(1, 4), (3, 3), (2, 2), (1, 1)]
[(1, 4), (3, 3), (2, 2), (3, 1)]
[(1, 4), (3, 3), (2, 2), (4, 1)]
[(1, 4), (3, 3), (4, 1)]
[(1, 4), (3, 3), (4, 2), (1, 1)]
[(1, 4), (3, 3), (4, 2), (2, 1)]
[(1, 4), (3, 3), (4, 2), (3, 1)]
[(1, 4), (4, 1)]
[(1, 4), (4, 2), (1, 1)]
[(1, 4), (4, 2), (2, 1)]
[(1, 4), (4, 2), (3, 1)]
[(1, 4), (4, 3), (1, 1)]
[(1, 4), (4, 3), (1, 2), (2, 1)]
[(1, 4), (4, 3), (1, 2), (3, 1)]
[(1, 4), (4, 3), (1, 2), (4, 1)]
[(1, 4), (4, 3), (2, 1)]
[(1, 4), (4, 3), (2, 2), (1, 1)]
[(1, 4), (4, 3), (2, 2), (3, 1)]
[(1, 4), (4, 3), (2, 2), (4, 1)]
[(1, 4), (4, 3), (3, 1)]
[(1, 4), (4, 3), (3, 2), (1, 1)]
[(1, 4), (4, 3), (3, 2), (2, 1)]
[(1, 4), (4, 3), (3, 2), (4, 1)]

How to get arrangement of two set without repeat by Python?

I have already got a method almost can do this:
from itertools import product
l = {1,2,3}
print(list(product(l,l)))
The output is:
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
However, I don't want to the set like (1,1), (2,2), (3,3)
and (2, 3), (3, 2) should only appear once since they are same in set concept.
So the exactly output I want is:
[(1, 2), (1, 3), (2, 1), (2, 3)]
How can I do this?
A simple method iterools.combinations
>>> import itertools
>>> list(itertools.combinations({1,2,3}, 2))
[(1, 2), (1, 3), (2, 3)]
>>>
You can apply a filter. For e.g.:
>>> from itertools import product
>>> l = {1,2,3}
>>> list(filter(lambda x: [x, None][x[0] == x[1]], list(product(l,l))))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
>>>

Python implementation of set relations

How would I implement the following using python? I've tried using lambda expressions and a few other methods, but I'm not getting the desired results. Basically, I should receive a set of relations that satisfy the check. I.E they have to be divisible by each other, so {(1,1), (1,2), (1,3),...(6,6)}.
Here's the actual question:
In Python, set a variable say S = {1,2,3,4,5,6}; then do as follows: "List all the ordered pairs in the relation R = {(a,b) : a divides b} on the set {1,2,3,4,5,6}."
you can do it by list comprehension -
S = [1,2,3,4,5,6]
result = [ (x,y) for x in S for y in S if y%x==0]
You can use itertools.product within a list comprehension,and as you want they be divisible by each other you can use the condition i%j==0 or j%i==0 :
>>> from itertools import product
>>> [(i,j) for i,j in product(S,repeat=2) if i%j==0 or j%i==0]
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 4), (2, 6), (3, 1), (3, 3), (3, 6), (4, 1), (4, 2), (4, 4), (5, 1), (5, 5), (6, 1), (6, 2), (6, 3), (6, 6)]
[{(a,b) : a/b} for a in S for b in S]

Categories

Resources