如何用LINQ筛选满足总和限制且总Energy最大的嵌套CookingRecipe集合
问题描述
现有如下C# CookingRecipe 类:
public class CookingRecipe { public int Index { get; set; } public int A { get; set; } public int B { get; set; } public int C { get; set; } public int Energy { get; set; } public CookingRecipe(int index, int a, int b, int c, int energie) { Index = index; A = a; B = b; C = c; Energy = energie; } }
已知三个整数 MaxA、MaxB、MaxC,以及一个 IEnumerable<IEnumerable<CookingRecipe>> 类型的集合 MyList。需求是:
- 先过滤出子集合中A的总和≤MaxA、B的总和≤MaxB、C的总和≤MaxC的项
- 再从过滤后的结果中获取总Energy最大的集合
目前已写出基础过滤代码:
var result = MyList.Where(x => x.Sum(y => y.A) <= MaxA && x.Sum(y => y.B) <= MaxB && x.Sum(y => y.C) <= MaxC);
需要在此基础上补充筛选总Energy最大的逻辑,用LINQ实现。
解决方案
1. 获取单个总Energy最大的集合(若有多个并列最大,只取第一个)
在过滤结果的基础上,按总Energy降序排序后取第一个元素即可:
var filtered = MyList.Where(x => x.Sum(y => y.A) <= MaxA && x.Sum(y => y.B) <= MaxB && x.Sum(y => y.C) <= MaxC); var maxEnergyRecipeSet = filtered.OrderByDescending(x => x.Sum(y => y.Energy)).FirstOrDefault();
如果能确定过滤后至少有一个符合条件的集合,也可以用 First() 替代 FirstOrDefault()。
2. 获取所有总Energy并列最大的集合
如果需要保留所有总Energy等于最大值的集合,可先算出最大总Energy值,再过滤出对应集合:
var filtered = MyList.Where(x => x.Sum(y => y.A) <= MaxA && x.Sum(y => y.B) <= MaxB && x.Sum(y => y.C) <= MaxC); if (!filtered.Any()) { // 此处处理无符合条件集合的场景 return; } int maxTotalEnergy = filtered.Max(x => x.Sum(y => y.Energy)); var maxEnergyRecipeSets = filtered.Where(x => x.Sum(y => y.Energy) == maxTotalEnergy).ToList();
3. 性能优化:避免重复计算总和
上面的写法中,每个子集合会被多次计算A、B、C、Energy的总和,当集合规模较大时会影响性能。可以先用 Select 提前计算好所有总和,再进行后续操作:
// 提前计算每个子集合的各项总和,避免重复遍历 var withTotals = MyList.Select(x => new { RecipeSet = x, TotalA = x.Sum(y => y.A), TotalB = x.Sum(y => y.B), TotalC = x.Sum(y => y.C), TotalEnergy = x.Sum(y => y.Energy) }); var filtered = withTotals.Where(item => item.TotalA <= MaxA && item.TotalB <= MaxB && item.TotalC <= MaxC); // 获取单个最大集合 var maxEnergySet = filtered.OrderByDescending(item => item.TotalEnergy).FirstOrDefault()?.RecipeSet; // 获取所有并列最大集合 if (filtered.Any()) { int maxEnergy = filtered.Max(item => item.TotalEnergy); var maxEnergySets = filtered.Where(item => item.TotalEnergy == maxEnergy).Select(item => item.RecipeSet).ToList(); }
这种方式每个子集合只被遍历计算一次各项总和,效率更高。
内容的提问来源于stack exchange,提问作者Fabrice76
相关产品推荐
相关产品推荐

