如何根据列表中最接近的Key更新列表对象的ValueToGet属性
根据最接近的Key匹配更新列表对象属性
我有两个列表:list(存储WidgetA对象)和listLookup(存储WidgetB对象)。需要根据listLookup中与WidgetA的Key值最接近的KeyLookup,更新list里所有WidgetA的ValueToGet属性。
原代码示例
using System.Collections.Generic; public class Program { public static void Main() { //Arrange //Keys needed to get ValueToGet property var key1 = new WidgetA{Id = 1, Key = 52}; var key2 = new WidgetA{Id = 2, Key = 102}; var key3 = new WidgetA{Id = 3, Key = 152}; List<WidgetA> list = new List<WidgetA>(); list.Add(key1); list.Add(key2); list.Add(key3); //Lookups var keyLookup1 = new WidgetB() {Id = 1, KeyLookup = 50, ValueLookup = "Fifty"}; var keyLookup2 = new WidgetB() {Id = 2, KeyLookup = 100, ValueLookup = "One hundred"}; var keyLookup3 = new WidgetB() {Id = 3, KeyLookup = 150, ValueLookup = "One hundred and fifty"}; List<WidgetB> listLookup = new List<WidgetB>(); listLookup.Add(keyLookup1); listLookup.Add(keyLookup2); listLookup.Add(keyLookup3); //Act /* Update all rows for ValueToGet property in list, using the closest KeyLookup in listLookup Expected result: key1: Key = 52, ValueToGet = "Fifty" key2: Key = 102, ValueToGet = "One hundred" key3: Key = 152, ValueToGet = "One hundred and fifty" */ } } public class WidgetA { public int Id { get; set; } public int Key { get; set; } public string ValueToGet { get; set; } } public class WidgetB { public int Id { get; set; } public int KeyLookup { get; set; } public string ValueLookup { get; set; } }
类似逻辑的SQL参考(需实现最接近匹配)
update list set ValueToGet = ValueLookup from list l1 join listLookup l2 on l1.key = l2.keyLookup
解决方案
核心思路是对每个WidgetA,计算其Key与所有WidgetB的KeyLookup的差值绝对值,找到差值最小的WidgetB,将其ValueLookup赋值给WidgetA的ValueToGet。可以利用LINQ简化实现:
//Act // 遍历每个WidgetA,找到最匹配的WidgetB并更新属性 foreach (var widgetA in list) { // 通过计算差值绝对值排序,取最接近的第一个匹配项 var closestMatch = listLookup .OrderBy(wb => Math.Abs(wb.KeyLookup - widgetA.Key)) .FirstOrDefault(); if (closestMatch != null) { widgetA.ValueToGet = closestMatch.ValueLookup; } } // 验证输出结果 foreach (var item in list) { System.Console.WriteLine($"key{item.Id}: Key = {item.Key}, ValueToGet = \"{item.ValueToGet}\""); }
代码说明
- 遍历
list中的每个WidgetA对象 - 对
listLookup中的WidgetB按「KeyLookup与当前WidgetA的Key的差值绝对值」从小到大排序 - 取排序后的第一个元素(即最接近的匹配项),将其ValueLookup赋值给WidgetA的ValueToGet
- 若
listLookup为空,FirstOrDefault会返回null,这里加了非空判断避免空引用
优化点(可选)
如果listLookup数据量较大,建议先对其按KeyLookup排序,再用二分查找快速定位最接近的值,能大幅提升查找效率:
// 先对lookup列表按KeyLookup排序 var sortedLookup = listLookup.OrderBy(wb => wb.KeyLookup).ToList(); foreach (var widgetA in list) { var targetKey = widgetA.Key; int left = 0, right = sortedLookup.Count - 1; int closestIndex = 0; while (left <= right) { int mid = (left + right) / 2; if (sortedLookup[mid].KeyLookup == targetKey) { closestIndex = mid; break; } else if (sortedLookup[mid].KeyLookup < targetKey) { closestIndex = mid; left = mid + 1; } else { right = mid - 1; } } // 检查下一个元素是否更接近 if (closestIndex < sortedLookup.Count - 1) { var currentDiff = Math.Abs(sortedLookup[closestIndex].KeyLookup - targetKey); var nextDiff = Math.Abs(sortedLookup[closestIndex + 1].KeyLookup - targetKey); if (nextDiff < currentDiff) { closestIndex++; } } widgetA.ValueToGet = sortedLookup[closestIndex].ValueLookup; }
内容的提问来源于stack exchange,提问作者Rod
相关产品推荐
相关产品推荐

