C#如何循环移除List<Location>中4个距指定点最近的元素
需求背景
现有初始化的地点集合如下:
List<Location> locations = new List<Location>(); locations.Add(new Location("Narayana International", 28.6075582, 77.04700729999999)); locations.Add(new Location("Digital zone", 28.8610328484855, 77.0951520020164)); locations.Add(new Location("Vijay computers", 28.841364952771706, 77.09076910484801)); locations.Add(new Location("Codac Info", 29.967759964202948, 76.88406425590289)); locations.Add(new Location("Balaji computers", 30.6920753011206, 76.80162611916126)); locations.Add(new Location("Aadi online exam solutions", 30.393033405609803, 76.79088732285474));
需要实现的逻辑:
- 计算所有剩余地点与指定坐标的距离,找到距离最近的地点打印到控制台
- 打印完成后将该地点从集合中移除
- 重复上述流程,直到累计移除4个元素为止
原代码缺陷
- 提前一次性计算所有点的距离存入字典,移除元素后字典数据不会同步更新,无法适配多轮查找的需求
- 固定调用
RemoveAt(0)移除索引为0的元素,和「移除当前最近点」的规则完全不符 - 没有做4次循环的流程控制,只能执行一次查找和固定位置移除操作
GetDistance方法里残留了调试用的打印语句,会输出大量无关的中间计算值
实现代码
首先确认Location类结构如下(已有定义可直接跳过):
public class Location { public string Place { get; set; } public double Latitude { get; set; } public double Longitude { get; set; } public Location(string place, double lat, double lng) { Place = place; Latitude = lat; Longitude = lng; } public override string ToString() { return Place; } }
核心逻辑实现:
// 初始化地点集合 List<Location> locations = new List<Location>(); locations.Add(new Location("Narayana International", 28.6075582, 77.04700729999999)); locations.Add(new Location("Digital zone", 28.8610328484855, 77.0951520020164)); locations.Add(new Location("Vijay computers", 28.841364952771706, 77.09076910484801)); locations.Add(new Location("Codac Info", 29.967759964202948, 76.88406425590289)); locations.Add(new Location("Balaji computers", 30.6920753011206, 76.80162611916126)); locations.Add(new Location("Aadi online exam solutions", 30.393033405609803, 76.79088732285474)); // 指定查询的基准坐标 double searchLat = 19; double searchLong = 74; int removeCount = 4; // 需要移除的元素总数 Console.WriteLine($"初始地点总数:{locations.Count}"); // 循环执行4次查找-打印-移除流程 for (int i = 0; i < removeCount; i++) { // 边界判断:剩余地点不足时直接终止 if (locations.Count == 0) break; Location nearest = null; double minDistance = double.MaxValue; // 遍历当前剩余所有地点,匹配最近点 foreach (var loc in locations) { double dist = GetDistance(loc.Latitude, loc.Longitude, searchLat, searchLong); if (dist < minDistance) { minDistance = dist; nearest = loc; } } // 打印最近点信息 Console.WriteLine($"第{i+1}次找到的最近地点:{nearest.Place},距离:{minDistance / 1000:F2}km"); // 从集合移除该点 locations.Remove(nearest); } Console.WriteLine($"流程结束,剩余地点数量:{locations.Count}"); Console.WriteLine("剩余地点列表:"); foreach (var item in locations) { Console.WriteLine(item.Place); } Console.ReadLine(); // 经纬度距离计算方法(Haversine公式,单位:米) public static double GetDistance(double latitude, double longitude, double otherLatitude, double otherLongitude) { var d1 = latitude * (Math.PI / 180.0); var num1 = longitude * (Math.PI / 180.0); var d2 = otherLatitude * (Math.PI / 180.0); var num2 = otherLongitude * (Math.PI / 180.0) - num1; var d3 = Math.Pow(Math.Sin((d2 - d1) / 2.0), 2.0) + Math.Cos(d1) * Math.Cos(d2) * Math.Pow(Math.Sin(num2 / 2.0), 2.0); return 6376500.0 * (2.0 * Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3))); }
逻辑说明
- 每一轮查找前都基于当前剩余的集合计算距离,避免提前缓存距离导致的数据不一致问题
- 遍历过程中直接记录最近的地点对象实例,不需要额外字典存储距离映射,内存占用更低、逻辑更直接
- 找到最近点后直接调用
Remove()方法传入实例对象即可精准移除,不需要依赖索引位置 - 增加集合为空的边界判断,避免元素不足时抛出空引用异常
- 距离输出做了单位转换(米转公里),可读性更好
内容的提问来源于stack exchange,提问作者Mahi Patil
相关产品推荐
相关产品推荐

