C# LINQ按ID匹配列表 解决多产品组筛选仅返回首项问题
问题描述
运行如下代码时,仅能获取productGroupIds中匹配到的第一个产品组对应的结果,无法返回所有符合条件的产品组关联数据:
var solutionItems = solutionInfoResponse .Items .Where(x => solutionInfoResponse .ProductGroup .FirstOrDefault(p => productGroupIds.Contains(p.GroupId)) .Items .Any(it => it.Id == x.ItemId)) .ToList();
涉及的相关类定义如下:
public class ProductGroup { public string GroupId { get; set; } public List<ProductGroupItem> Items { get; set; } } public class ProductGroupItem { public string Id { get; set; } public string Description { get; set; } } public class SolutionItem { public string ItemId { get; set; } } public class SolutionInfoResponse { public List<SolutionItem> Items { get; set; } public SolutionInfo SolutionInfo { get; set; } public List<ProductGroup> ProductGroup { get; set; } }
问题原因
原逻辑使用FirstOrDefault()筛选产品组,该方法只会返回第一个GroupId在productGroupIds中的产品组实例,后续的条目匹配完全基于这单个产品组的Items集合,因此其他符合GroupId要求的产品组下的条目会被全部忽略。
同时该写法存在空引用风险:如果没有任何产品组匹配productGroupIds,FirstOrDefault()会返回null,后续访问.Items时会直接抛出空引用异常。
修复方案
先筛选出所有GroupId命中productGroupIds的产品组,提取这些产品组下所有条目的Id组成集合,再基于这个Id集合过滤SolutionItem即可,同时增加空值校验避免运行时异常:
// 提取所有匹配产品组下的有效条目Id,用HashSet提升匹配性能 var validItemIds = solutionInfoResponse.ProductGroup .Where(pg => productGroupIds.Contains(pg.GroupId)) // 筛选所有符合GroupId要求的产品组,而非仅取第一个 .SelectMany(pg => pg.Items ?? new List<ProductGroupItem>()) // 摊平所有产品组下的条目,兼容Items为null的场景 .Select(it => it.Id) .ToHashSet(); // 过滤出ItemId在有效Id集合中的SolutionItem var solutionItems = solutionInfoResponse.Items .Where(x => validItemIds.Contains(x.ItemId)) .ToList();
逻辑说明
- 用
Where()替代FirstOrDefault()筛选产品组,确保所有GroupId符合要求的产品组都被纳入计算范围 - 用
SelectMany()将多个产品组下的Items集合摊平为单个条目序列,避免多层嵌套遍历 - 提前提取有效Id存入
HashSet,后续匹配时间复杂度为O(1),相比嵌套Any()的O(n)写法性能更优 - 对Items集合增加空值兼容,避免产品组的Items属性为null时抛出空引用异常
内容的提问来源于stack exchange,提问作者Kutty Rajesh Valangai
相关产品推荐
相关产品推荐

