如何动态遍历嵌套复杂的多个IEnumerable?两种场景实现问询
高效遍历复杂嵌套IEnumerable的实现方案
看起来你需要处理嵌套程度较高的集合遍历问题——针对Dictionary<int, List<Entity>[]>这种结构,实现筛选特定组合子集遍历和全量子集遍历两种逻辑。我先修正你示例中的Linq语法问题,再给出更合理的实现方案,兼顾代码简洁性和性能。
场景1:筛选特定键+指定数组索引的组合遍历
你示例里SelectMany(i = 1, i = 4)的写法不符合Linq规范,我们可以先锁定目标键的范围,再提取对应数组中指定索引的列表,最后扁平化所有Entity。
实现代码
// 先定义要筛选的目标键集合(比如1到4) var targetKeys = new HashSet<int> { 1, 2, 3, 4 }; // 用HashSet提升查询效率 // 链式Linq查询:筛选键 → 提取指定索引的列表 → 扁平化所有Entity var filteredEntities = submeshes .Where(kv => targetKeys.Contains(kv.Key)) // 只保留目标键的条目 .SelectMany(kv => new[] { kv.Value[0], kv.Value[2] }) // 取每个数组的第0和第2个列表 .SelectMany(entityList => entityList); // 把所有列表里的Entity摊平成一维集合 // 遍历执行更新 foreach (Entity e in filteredEntities) { e.Update(); }
小优化
如果targetKeys是动态生成的范围(比如从start到end),可以用Enumerable.Range(start, count)生成,再转成HashSet:
var targetKeys = Enumerable.Range(1, 4).ToHashSet();
场景2:遍历所有键+指定数组索引的全量遍历
这个场景更直接,不需要筛选键,直接遍历字典所有条目,提取指定索引的列表并扁平化即可。
实现代码
// 提取所有数组中第0个列表的所有Entity var allTargetEntities = submeshes .SelectMany(kv => kv.Value[0]) // 直接取每个数组的第0个列表并摊平 .ToList(); // 可选:如果需要重复遍历,提前转成List缓存结果,避免重复执行Linq查询 // 遍历更新 foreach (Entity e in allTargetEntities) { e.Update(); }
扩展:动态指定索引
如果需要灵活切换要提取的数组索引(比如有时候取[0],有时候取[2]),可以封装成复用方法:
IEnumerable<Entity> GetEntitiesByIndex(Dictionary<int, List<Entity>[]> submeshes, int targetIndex) { // 加上空值和索引越界检查,避免报错 return submeshes.SelectMany(kv => kv.Value != null && targetIndex >= 0 && targetIndex < kv.Value.Length ? kv.Value[targetIndex] : Enumerable.Empty<Entity>()); } // 使用示例 foreach (Entity e in GetEntitiesByIndex(submeshes, 0)) { e.Update(); }
性能与可靠性提示
- 延迟执行特性:Linq查询默认是延迟执行的,只有在
foreach遍历或调用ToList()/ToArray()时才会真正执行。如果你的submeshes集合在查询后可能被修改,建议提前调用ToList()缓存结果。 - 空值防护:如果集合存在空条目或数组索引可能越界,一定要加上空值和范围检查,避免运行时异常。
- 大集合优化:如果
List<Entity>是超大集合,尽量减少中间集合的创建,直接通过SelectMany扁平化可以降低内存开销。
内容的提问来源于stack exchange,提问作者Mechandrius
相关产品推荐
相关产品推荐

