For a list of (x, y) points, I am trying to find the nearby points for each point.
from collections import defaultdict
from math import sqrt
from random import randint
# Generate a list of random (x, y) points
points = [(randint(0, 100), randint(0, 100)) for _ in range(1000)]
def is_nearby(point_a, point_b, max_distance=5):
    """Two points are nearby if their Euclidean distance is less than max_distance"""
    distance = sqrt((point_b[0] - point_a[0])**2 + (point_b[1] - point_a[1])**2)
    return distance < max_distance
# For each point, find nearby points that are within a radius of 5
nearby_points = defaultdict(list)
for point in points:
    for neighbour in points:
        if point != neighbour:
            if is_nearby(point, neighbour):
                nearby_points[point].append(neighbour)
Is there any way I can index points to make the above search faster? I feel there must be some faster way than O(len(points)**2).
Edit: the points in general could be floats, not just ints
                        
this is a version with a fixed grid where each gridpoint holds the number of samples that are there.
the search can then be reduced to just the space around the point in question.
for further optimzation: the tests for
xandycould be precalculated for a given gridsize - themath.hypot(point[0]-x, point[1]-y)would not have to be done then for every point.and it may be a good idea to replace the grid with a
numpyarray.UPDATE
if your points are
floats you can still create anintgrid to reduce the search space:the output looks something like this:
for convenience
Pointsis now a class. may not be necessary though...depending on how dense or sparse your points are you could also represent the grid as a dictionary pointing to a list or
Points...also the
find_neighboursfunction accepts a startingpointconsisting ofints only in that version. this might also be refined.and there is much room for improvement: the range of the
yaxis can be restricted using trigonometry. and for the points way inside the circle there is no need for an individual check; detailed checking only needs to be done close to the outer rim of the circle.