Python - Group Adjacent Coordinates
Last Updated :
03 Mar, 2023
Sometimes, while working with Python lists, we can have a problem in which we need to perform the grouping of all the coordinates which occur adjacent on a matrix, i.e horizontally and vertically at distance 1. This is called Manhattan distance. This kind of problem can occur in competitive programming domain. Let's discuss certain way in which this task can be performed.
Input : test_list = [(4, 4), (6, 4), (7, 8)]
Output : [[(7, 8)], [(6, 4)], [(4, 4)]]
Input : test_list = [(4, 4), (5, 4)]
Output : [[(5, 4), (4, 4)]]
Method 1: Using product() + groupby() + list comprehension
The combination of above methods can be used to solve this problem. In this, we perform the task of grouping of elements using groupby() and check for pairs using product(). The logic driving this solution is similar to union find algorithm.
Python3
# Python3 code to demonstrate working of
# Group Adjacent Coordinates
# Using product() + groupby() + list comprehension
from itertools import groupby, product
def Manhattan(tup1, tup2):
return abs(tup1[0] - tup2[0]) + abs(tup1[1] - tup2[1])
# initializing list
test_list = [(4, 4), (6, 4), (7, 8), (11, 11),
(7, 7), (11, 12), (5, 4)]
# printing original list
print("The original list is : " + str(test_list))
# Group Adjacent Coordinates
# Using product() + groupby() + list comprehension
man_tups = [sorted(sub) for sub in product(test_list, repeat = 2)
if Manhattan(*sub) == 1]
res_dict = {ele: {ele} for ele in test_list}
for tup1, tup2 in man_tups:
res_dict[tup1] |= res_dict[tup2]
res_dict[tup2] = res_dict[tup1]
res = [[*next(val)] for key, val in groupby(
sorted(res_dict.values(), key = id), id)]
# printing result
print("The grouped elements : " + str(res))
OutputThe original list is : [(4, 4), (6, 4), (7, 8), (11, 11), (7, 7), (11, 12), (5, 4)]
The grouped elements : [[(6, 4), (5, 4), (4, 4)], [(7, 8), (7, 7)], [(11, 12), (11, 11)]]
Time complexity: O(n log n)., where n is the length of the input list test_list.
Auxiliary space: O(n^2), as the man_tups list and the res_dict dictionary both have n^2 elements.
Method 2: Using numpy() :
1.Define a function manhattan that takes two tuples and returns the Manhattan distance between them.
2.Create a NumPy array test_arr from the given list of tuples test_list.
3.Create two arrays x and y by unpacking the coordinates from test_arr.
4.Use np.meshgrid to create two 2D arrays xx and yy of all possible pairwise combinations of x and y.
5.Use np.dstack to stack xx and yy into a 3D array grid.
6.Use np.apply_along_axis to apply manhattan to the last two dimensions of grid to get a 2D array man_tups of tuples whose Manhattan distance is 1.
7.Use a dictionary comprehension to create a dictionary res_dict where each key is a coordinate from test_arr and each value is a set containing that coordinate.
8.Loop through the pairs of tuples in man_tups, update the corresponding sets in res_dict, and merge the sets.
9.Use a dictionary comprehension to create a dictionary res_dict2 where each key is a frozenset of the sets in res_dict.values() and each value is the first set in that frozenset.
10.Create a list res by looping through the values of res_dict2 and converting each set to a list.
Python3
import numpy as np
from itertools import groupby, product
def Manhattan(tup1, tup2):
return abs(tup1[0] - tup2[0]) + abs(tup1[1] - tup2[1])
# initializing list
test_list = [(4, 4), (6, 4), (7, 8), (11, 11),
(7, 7), (11, 12), (5, 4)]
# printing original list
print("The original list is : " + str(test_list))
# Group Adjacent Coordinates
# Using product() + groupby() + list comprehension
man_tups = [sorted(sub) for sub in product(test_list, repeat = 2)
if Manhattan(*sub) == 1]
res_dict = {ele: {ele} for ele in test_list}
for tup1, tup2 in man_tups:
res_dict[tup1] |= res_dict[tup2]
res_dict[tup2] = res_dict[tup1]
res = [[*next(val)] for key, val in groupby(
sorted(res_dict.values(), key = id), id)]
# converting tuples to numpy arrays
res = [np.array(sub) for sub in res]
# sorting numpy arrays lexicographically
res = sorted(res, key=lambda x: tuple(x[:,0]))
# converting numpy arrays back to tuples
res = [tuple(map(tuple, sub)) for sub in res]
# printing result
print("The grouped elements : " + str(res))
#This code is contributed by Jyothi pinjala.
Output:
The original list is : [(4, 4), (6, 4), (7, 8), (11, 11), (7, 7), (11, 12), (5, 4)]
The grouped elements : [((4, 4), (5, 4), (6, 4)), ((7, 7), (7, 8)), ((11, 12), (11, 11))]
The time complexity : O(n^2), where n is the number of coordinates in the input list. This is because it involves a nested loop over all pairs of coordinates to compute their Manhattan distance, which takes O(n^2) time. Additionally, there is a loop over the resulting list of adjacent coordinate pairs to construct the groups, which takes O(n) time in the worst case.
The auxiliary space :O(n^2), due to the creation of the manhattan distance matrix. This matrix has n^2 elements, each of which is a 32-bit integer (assuming the default data type for numpy arrays), so it requires O(n^2 * 4 bytes) = O(n^2) space. Additionally, the output list of groups may require up to O(n) space in the worst case.
Similar Reads
Python - Adjacent Coordinates in N dimension Sometimes, while working with Python Matrix, we can have a problem in which we need to extract all the adjacent coordinates of the given coordinate. This kind of problem can have application in many domains such as web development and school programming. Lets discuss certain way in which this task c
3 min read
Python - Adjacent elements in List Given a List extract both next and previous element for each element. Input : test_list = [3, 7, 9, 3] Output : [(None, 7), (3, 9), (7, 3), (9, None)] Explanation : for 7 left element is 3 and right, 9. Input : test_list = [3, 7, 3] Output : [(None, 7), (3, 3), (7, None)] Explanation : for 7 left el
3 min read
Python - Group dates in K ranges Given a list of dates, group the dates in a successive day ranges from the initial date of the list. We will form a group of each successive range of K dates, starting from the smallest date. Input : test_list = [datetime(2020, 1, 4), datetime(2019, 12, 30), datetime(2020, 1, 7), datetime(2019, 12,
6 min read
Python | Group list elements based on frequency Given a list of elements, write a Python program to group list elements and their respective frequency within a tuple. Examples: Input : [1, 3, 4, 4, 1, 5, 3, 1] Output : [(1, 3), (3, 2), (4, 2), (5, 1)] Input : ['x', 'a', 'x', 'y', 'a', 'x'] Output : [('x', 3), ('a', 2), ('y', 1)] Method #1: List c
5 min read
Python - Group Consecutive elements by Sign Given a list group of consecutive elements on the basis of signs. Input : test_list = [5, -3, 2, 4, 6, -2, -1, -7, -9, 2, 3]Â Output : [[5], [-3], [2, 4, 6], [-2, -1, -7, -9], [2, 3]]Â Explanation : Elements inserted into new list on sign change.Input : test_list = [-2,3,4,5,6,-3] Output : [[-2], [3
3 min read