LINQ查找最接近的坐标

5

我有一个包含坐标(x,y)的数据库,并希望找到最接近某个点的坐标。(可能有多个与该点最接近的坐标)

我已经写了这2个LINQ,但肯定有比两次遍历数据库更聪明的方法:

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)));

怎样优化这个问题?


顺便提一下,如果你只想找到最近的值(而不是实际距离),你不需要对值进行平方根运算。 - Matthew Watson
你能不能不使用kd树? - vc 74
@Matthew,老实说我不知道... Math.Pow 应该很容易解决... 如果 EF 无法翻译,我的问题仍然是,如何只进行一次完整的表扫描而不是现在的两次来实现我想要的结果。 - sirius
@VC 74。我宁愿不将其加载到内存中,因为表格包含大量数据。 - sirius
2个回答

8
  1. 您不能计算Math.Sqrt - 这并不重要(3>2且3*3>2*2)
  2. 您可以按距离排序并取第一个:

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

此外,将Math.Pow替换为乘法 - 这将更快:
var closest = _context.Coordinates.OrderBy(x =>
               (point.coordX - x.CoordX) * (point.coordX - x.CoordX) + (point.WinningCoordY - x.CoordY) * (point.WinningCoordY - x.CoordY))
             .First();

你提出了一些很好的观点。感谢你的帮助。我需要的不仅仅是第一个,但如果我按照Christos的建议进行groupBy操作,我认为我已经得到了我所需的。 - sirius
@sirius,我不小心忽略了你的问题并错过了关于多个点的要求,所以我可以通过分组来改进我的答案。但我建议你替换Math.Pow。 - Backs

6
你可以使用分组功能。此外,您不必计算平方根,只需使用相应差的平方和即可。
使用GroupBy,您可以构建一系列组,其键是每个组中点与您感兴趣的点之间的距离。然后,您可以根据键的值对组进行OrderBy。最后,选择第一组。其中包含您要查找的点。
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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接