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

C# WinForm中将子集求和结果回写至原有DataTable的实现咨询

实现方案

步骤1:调整数据读取与子集生成逻辑

原有逻辑仅存储了子集的数值拼接结果与求和值,需要调整为同时存储子集对应行的Sno编号,方便后续回写DataTable。默认你原表的Sno列为主键唯一列,若还未新增标签列先执行以下代码:

// 标签列已存在可跳过本段
if (!dm.Columns.Contains("标签"))
{
    dm.Columns.Add("标签", typeof(string));
}

调整后的数据读取与子集生成代码如下:

// 同时读取每行的唯一Sno和待计算数值
var rowData = dm.AsEnumerable()
    .Select(r => new { Sno = r.Field<int>("Sno"), Value = double.Parse(r.Field<string>(dm.Columns[2])) })
    .ToList();
double[] arrDouble = rowData.Select(x => x.Value).ToArray();

// 子集存储结构调整为:Item1=选中行的Sno集合,Item2=子集求和结果
List<Tuple<List<int>, double>> list = new List<Tuple<List<int>, double>>();
list.Add(new Tuple<List<int>, double>(new List<int> { rowData[0].Sno }, arrDouble[0]));

for (int i = 1; i < arrDouble.Length; i++)
{
    var newlist = new List<Tuple<List<int>, double>>();
    list.ForEach(l => 
    {
        var newSnoList = new List<int>(l.Item1) { rowData[i].Sno };
        newlist.Add(new Tuple<List<int>, double>(newSnoList, l.Item2 + arrDouble[i]));
    });
    list.Add(new Tuple<List<int>, double>(new List<int> { rowData[i].Sno }, arrDouble[i]));
    list.AddRange(newlist);
}

步骤2:保留最优解筛选逻辑

原有筛选逻辑基本不变,仅需调整变量接收包含Sno集合的最优解:

double sumN = arrDouble.Sum();
double targetN = 你的目标求和值; // 替换为实际业务的目标数值

Tuple<List<int>, double> solution2;
if (sumN > targetN)
{
    solution2 = list.Where(l => l.Item2 >= targetN).OrderBy(o => o.Item2).First();
}
else
{
    solution2 = list.Where(l => l.Item2 >= sumN).OrderBy(o => o.Item2).Last();
}

double lowest_weight = list.Min(c => c.Item2);
Tuple<List<int>, double> solution1;
if (targetN > lowest_weight)
{
    solution1 = list.Where(l => l.Item2 <= targetN).OrderBy(o => o.Item2).Last();
}
else
{
    solution1 = list.Where(l => l.Item2 >= targetN).OrderBy(o => o.Item2).First();
}

// 选出距离目标值最近的最终最优解
Tuple<List<int>, double> finalSolution = 
    Math.Abs(solution2.Item2 - targetN) < Math.Abs(solution1.Item2 - targetN) 
    ? solution2 : solution1;

步骤3:回写标签列到DataTable

拿到最优解包含的Sno集合后,直接匹配对应行写入标签即可:

// 清空历史标签
foreach (DataRow row in dm.Rows)
{
    row["标签"] = DBNull.Value;
}

// 给最优子集包含的行写入对应Sno,可根据需求自定义标签格式
foreach (int sno in finalSolution.Item1)
{
    DataRow matchRow = dm.AsEnumerable().First(r => r.Field<int>("Sno") == sno);
    matchRow["标签"] = sno.ToString();
}

注意事项

  • 现有子集生成逻辑时间复杂度为O(2^n),仅适合行数不超过20的小数据量场景,行数过多会出现严重性能问题。
  • 若你的Sno列名称和默认不一致,需替换代码中对应的列名为实际名称。

内容的提问来源于stack exchange,提问作者Muhammad Sajid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 17:48:05