sirius
sirius

Reputation: 220

LINQ find closest coordinates

I'm having a database full of coordinates (x,y), and i wish to find the coordinates closest to a point. (there can be multiple closest to this point)

I've written this 2 LINQ's, but there must be a smarte way, than going through the database two times:

var closestDistance = _context.Coordinates.Min(x =>
                          Math.Sqrt(Math.Pow((point.coordX - x.CoordX), 2) +
                                    Math.Pow((point.coordY- x.CoordY), 2)));
var closest = _context.Coordinates.Where(x=> closestDistance ==
                          Math.Sqrt(Math.Pow((point.coordX - x.CoordX), 2) +
                                    Math.Pow((point.coordY - x.CoordY), 2)));

How can i optimize this?

Upvotes: 5

Views: 3943

Answers (2)

Christos
Christos

Reputation: 53958

You could make use of a group by. Furthermore, you don't have to calculate the square root. You could just use the sum of the squares of the corresponding differences.

Using the GroupBy, you build a sequence of groups, whose key is the distance of the points of each group from the point you are interested in. Then you make an OrderBy of the groups based on the key's value. Last you pick the first group. This contains the points you are looking for.

var closest = _context.Coordinates
                      .GroupBy(x => Math.Pow((point.coordX - x.CoordX), 2) + Math.Pow((point.WinningCoordY - x.CoordY), 2))
                      .OrderBy(x=>x.Key)
                      .First();

Upvotes: 6

Backs
Backs

Reputation: 24923

  1. You can not calc Math.Sqrt - it does not matter (3 > 2 and 3*3 > 2*2)
  2. You can sort by dist and take first:

var closest = _context.Coordinates.OrderBy(x =>
               Math.Pow((point.coordX - x.CoordX), 2) + Math.Pow((point.WinningCoordY - x.CoordY), 2))
             .First();
  1. Also, replace Math.Pow with multiplication - it will be much faster:

var closest = _context.Coordinates.OrderBy(x =>
               (point.coordX - x.CoordX) * (point.coordX - x.CoordX) + (point.WinningCoordY - x.CoordY) * (point.WinningCoordY - x.CoordY))
             .First();

Upvotes: 8

Related Questions