You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据列表中最接近的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}\"");
}

代码说明

  1. 遍历list中的每个WidgetA对象
  2. 对listLookup中的WidgetB按「KeyLookup与当前WidgetA的Key的差值绝对值」从小到大排序
  3. 取排序后的第一个元素(即最接近的匹配项),将其ValueLookup赋值给WidgetA的ValueToGet
  4. 若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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 04:05:21