I have a list with a pair of coordinates: e.g. coord_list = [[1,2]] For this coordinate, I would like to append to the list coordinates that are /- 2 points away from both the x and y coordinates. The list will contain 25 pairs of coordinates in the end, with the centre coordinate as the first element.
Any suggestions about how to go about this in Python? Thanks a lot.
CodePudding user response:
The Solution
We can construct from the x
and y
coordinate of the point
the range of numbers of the points which are surrounding the point
by up to k = 2
.
Then we build all possible combinations of these possible x
and y
coordinate values.
This can be neatly done with list expressions by combining two for-clauses.
Due to your desire that the original point should be placed at the beginning, we add an if [x, y] != point
clause to exclude the
original point from listing by the list-expression but we add it at the beginning extra to this list-comprehension [point] [ <list-comprehension>]
.
The nice thing of this solution is that you can vary k
, e.g. k=3
or just one layer of cells around the original cell by setting k=1
.
def vary_around(val, k=2):
return list(range(val - k, val k 1))
def points_around(point, k=2):
x, y = point
xs = vary_around(x, k=k)
ys = vary_around(y, k=k)
return [point] [[x, y] for x in xs for y in ys if [x, y] != point]
Test It
You can try it:
In [39]: points_around([1, 2], k=2)
Out[39]:
[[1, 2],
[-1, 0],
[-1, 1],
[-1, 2],
[-1, 3],
[-1, 4],
[0, 0],
[0, 1],
[0, 2],
[0, 3],
[0, 4],
[1, 0],
[1, 1],
[1, 3],
[1, 4],
[2, 0],
[2, 1],
[2, 2],
[2, 3],
[2, 4],
[3, 0],
[3, 1],def points_around(point, k=2):
x, y = point
xs = vary_around(x, k=k)
ys = vary_around(y, k=k)
return {tuple(point): [[x, y] for x in xs for y in ys if [x, y] != point]}
# now, you get:
reduce(lambda dct, dct1: dct.update(dct1) and dct, [points_around(point, k=2) for point in coord_list])
[3, 2],
[3, 3],
[3, 4]]
In [40]: len(points_around([1, 2], k=2))
Out[40]: 25
With:
coord_list = [[1, 2], [3, 4]]
You apply this function again using list-comprehensions:
point_groups = [points_around(point, k=2) for point in coord_list]
Further Suggestion
Probably you want the original point at the beginning to have it distinguished from the rest of the points.
How about using a dictionary for this purpose?
def merge_dicts(dct, dct1):
dct.update(dct1)
return dct
def points_around(point, k=2):
x, y = point
xs = vary_around(x, k=k)
ys = vary_around(y, k=k)
return {tuple(point): tuple([(x, y) for x in xs for y in ys if [x, y] != point])} # key must be a tuple and not a list
# in a dictionary so probably better to make everything a tuple
from functools import reduce
defun coords_to_points_dict(coord_list, k=2):
return reduce(merge_dicts, [points_around(point, k=k) for point in coord_list])
point2surrounding_points = coords_to_points_dict(coord_list, k=2)
point2surrounding_points
# it outputs:
{(1, 2): ((-1, 0),
(-1, 1),
(-1, 2),
(-1, 3),
(-1, 4),
(0, 0),
(0, 1),
(0, 2),
(0, 3),
(0, 4),
(1, 0),
(1, 1),
(1, 3),
(1, 4),
(2, 0),
(2, 1),
(2, 2),
(2, 3),
(2, 4),
(3, 0),
(3, 1),
(3, 2),
(3, 3),
(3, 4)),
(3, 4): ((1, 2),
(1, 3),
(1, 4),
(1, 5),
(1, 6),
(2, 2),
(2, 3),
(2, 4),
(2, 5),
(2, 6),
(3, 2),
(3, 3),
(3, 5),
(3, 6),
(4, 2),
(4, 3),
(4, 4),
(4, 5),
(4, 6),
(5, 2),
(5, 3),
(5, 4),
(5, 5),
(5, 6))}
This dictionary you can query with your points to get their surrounding points.
CodePudding user response:
You could use a list comprehension to generate the 24 additional coordinates and append them to the original list:
coords = [[1,2]]
coords = [ [x d//5-2,y d%5-2] for x,y in coords
for d in range(25) if d != 12 ]
print(coords)
[[1, 2], [-1, 0], [-1, 1], [-1, 2], [-1, 3],
[-1, 4], [0, 0], [0, 1], [0, 2], [0, 3],
[0, 4], [1, 0], [1, 1], [1, 3], [1, 4],
[2, 0], [2, 1], [2, 2], [2, 3], [2, 4],
[3, 0], [3, 1], [3, 2], [3, 3], [3, 4]]
You could generalize it into a function for any distance like this:
def addNeighbors(coords,distance=2):
coords = [ [x dx,y dy] for x,y in coords
for dx in range(-distance,distance 1)
for dy in range(-distance,distance 1)
if dx or dy ]