You can use numpy.linalg.norm()
to calculate the Euclidean distance between two numpy array. So you can declare those position arrays as a numpy array and apply this function to calculate distance.
Let's see this step by step.
- Declared initial
current_pos
as origin (0,0)
. Extracted the points sequentially in the list named pos_list
. Declared result_list
as empty list to fetch results.
- From the
pos_list
each positions can be taken and Euclidean distance with current_pos
is calculated and stored in the dist_list
.
- The
min(dist_list)
gives the minimum distance min_dist
. The corresponding index of min_dist
can be fetched from dist_list
and the relevant position and entry of the input data can be identified and processed (i.e. removing from data
and appending to result_list
)
- The whole process continues until the
data
becomes empty.
The whole implementation:
import numpy as np
data = [{5036885850: [92.0, 88.73]}, {5036885955: [90.0, 61.73]}, {5036885984: [86.0, 73.03]}, {5036885998: [102.0, 77.54]}]
pos_list = [list(item.values())[0] for item in data]
current_pos = np.array([0,0])
result_list = []
while (len(data) != 0):
dist_list = [np.linalg.norm(current_pos - np.array(pos)) for pos in pos_list]
min_dist = min(dist_list)
item_index = dist_list.index(min_dist)
to_be_moved = data[item_index]
result_list.append(to_be_moved)
# current_pos = pos_list[item_index]
pos_list.remove(pos_list[item_index])
data.remove(to_be_moved)
print(result_list)
You're requirement was not clear in the question, so I'm handling two cases.
First case: Arrange the points in such an order such that the distances of each points from the origin is increasing. The above code works for this scenario and this matches your expected output.
Second case: Arrange the points a,b,c,d,...
in such a way so that a is nearest to origin, b is nearest to a, c is nearest to d and so on. To see this case in action just revert the commented line.
NOTE: If any type of sort or positional modification is done, this solution will break.
UPDATE
According to your last added condition, you need to calculate the centroid of all the points in the resulting order, then find the order that is closest to the centroid.
You can pass the list of points that has been already added to the result find the centroid with the following function:
def get_centroid(lst):
arr = np.array(lst)
length = arr.shape[0]
if length == 0:
return 0,0
else:
sum_x = np.sum(arr[:, 0])
sum_y = np.sum(arr[:, 1])
return sum_x/float(length), sum_y/float(length)
to do so, keep a track of the point that is added to the final result and removed from the pos_list
in another list called pos_removed_list
:
pos_removed_list.append(pos_list[item_index])
and replace the commented line:
# current_pos = pos_list[item_index]
with
current_pos = np.array(get_centroid(pos_removed_list))
and you're ready to go!
**Full Code: **
import numpy as np
def get_centroid(lst):
arr = np.array(lst)
length = arr.shape[0]
if length == 0:
return 0,0
else:
sum_x = np.sum(arr[:, 0])
sum_y = np.sum(arr[:, 1])
return sum_x/float(length), sum_y/float(length)
data = [{5036885850: [92.0, 88.73]}, {5036885955: [90.0, 61.73]}, {5036885984: [86.0, 73.03]}, {5036885998: [102.0, 77.54]}]
pos_list = [list(item.values())[0] for item in data]
pos_removed_list = []
current_pos = np.array((0,0))
result_list = []
print('initial centroid: ' + str(current_pos))
while (len(data) != 0):
dist_list = [np.linalg.norm(current_pos - np.array(pos)) for pos in pos_list]
min_dist = min(dist_list)
item_index = dist_list.index(min_dist)
to_be_moved = data[item_index]
print('moved: ' + str(to_be_moved))
result_list.append(to_be_moved)
pos_removed_list.append(pos_list[item_index])
pos_list.remove(pos_list[item_index])
current_pos = np.array(get_centroid(pos_removed_list))
print('current centroid: ' + str(current_pos))
data.remove(to_be_moved)
print('\nfinal result: ' + str(result_list))
Your step by step output will be:
initial centroid: [0 0]
moved: {5036885955: [90.0, 61.73]}
current centroid: [90. 61.73]
moved: {5036885984: [86.0, 73.03]}
current centroid: [88. 67.38]
moved: {5036885998: [102.0, 77.54]}
current centroid: [92.66666667 70.76666667]
moved: {5036885850: [92.0, 88.73]}
current centroid: [92.5 75.2575]
final result: [{5036885955: [90.0, 61.73]}, {5036885984: [86.0, 73.03]}, {5036885998: [102.0, 77.54]}, {5036885850: [92.0, 88.73]}]
Let me know if this is what you were looking for