Search code examples
pythonpython-2.7splitcoordinatesinstance

How to split list of (X,Y) coordinates of path into separate list of X and Y coordinates?


In the following function, 'graph' is a 2d grid list consisting of ones, zeroes and a 'two' (of obstacles, open areas and target respectively), 'start' is the point to start the search from.

def bfs(graph, start):

fringe = [[start]]
# Special case: start == goal
if start.val == 'g':
    return [start]
start.visited = True
# Calculate width and height dynamically. We assume that "graph" is dense.
width = len(graph[0])
height = len(graph)
# List of possible moves: up, down, left, right.

moves = [(-1, 0), (1, 0), (0, -1), (0, 1)]
while fringe:
    # Get first path from fringe and extend it by possible moves.

    path = fringe.pop(0)
    #print path
    node = path[-1]
    pos = node.pos
    # Using moves list (without all those if's with +1, -1 etc.) has huge benefit:
    # moving logic is not duplicated. It will save you from many silly errors.

    for move in moves:
        # Check out of bounds. Note that it's the ONLY place where we check it.
        if not (0 <= pos[0] + move[0] < height and 0 <= pos[1] + move[1] < width):
            continue
        neighbor = graph[pos[0] + move[0]][pos[1] + move[1]]
        if neighbor.val == 'g':
            return path + [neighbor]
        elif neighbor.val == 'o' and not neighbor.visited:
            neighbor.visited = True
            fringe.append(path + [neighbor])  # creates copy of list
raise Exception('Path not found!')

TRANSLATE = {0: 'o', 1: 'x', 2: 'g'}
graph = [[Node(TRANSLATE[x], (i, j)) for j, x in enumerate(row)] for i, row in enumerate(graph)]
# Find path
path = bfs(graph, graph[4][4])

When I print the value of path, the following is what I get:

Path [(4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (3, 8), (2, 8), (1, 8), (1, 9)]

These are x and y coordinates.

Now how do I get the coordinates as a list of seperate 'x' and 'y' coordinates?

My preferred output is

X_list=[4,4,4,4,4,3,2,1,1]
Y_list=[4,5,6,7,8,8,8,8,9]

P.S: When I check the "type of" the printed path, it is showing it as an 'instance'.

Please help me as I am stuck at this point after a lot of searches to achieve my preferred output.

I request you to enlighten me on this. Thanks a lot!!


Solution

  • You can transpose and map the tuples to lists or use map and itemgetter.

    from operator import itemgetter
    l = [(4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (3, 8), (2, 8), (1, 8), (1, 9)]
    
    a,b = map(itemgetter(0),l), map(itemgetter(1),l)
    print(a,b)
    
    a,b = map(list,zip(*l))
    
    print(a,b)
    [4, 4, 4, 4, 4, 3, 2, 1, 1] [4, 5, 6, 7, 8, 8, 8, 8, 9]
    [4, 4, 4, 4, 4, 3, 2, 1, 1] [4, 5, 6, 7, 8, 8, 8, 8, 9]
    

    You need to add iter in your class so you can iterate over the objects:

     def __iter__(self):
            return iter(self.coords)
    
    class Node():
        def __init__(self, pos):
            self.pos = pos
    
        def __iter__(self):
            return iter(self.pos)
    
    l = []
    for x in [(1, 5), (2, 6), (3, 7), (4, 8)]:
        l.append(Node(x))
    
    
    print("{}".format(list(map(list,zip(*l)))))
    
    [[1, 2, 3, 4], [5, 6, 7, 8]]
    

    For bfs using a Queue would be an efficient solution: