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

使用C# LINQ过滤三层嵌套集合并保留原层级结构的技术实现

How to Filter Nested Collections (Collection→Repo→Workflow) While Preserving Hierarchy in LINQ

Let's fix this nested filtering issue step by step. Your current implementation uses SelectMany which flattens the hierarchy, resulting in just a list of matching Workflow objects instead of preserving the parent Repo and Collection structure. Here's how to adjust the logic to keep the full nested hierarchy while filtering correctly:

Key Requirements Recap

We need to:

  • Match any level's Name property (Collection/Repo/Workflow) against the filter string (case-insensitive, based on your example)
  • Keep only matching items and their parent hierarchy
  • Maintain the original nested structure (List<Collection> → List<Repo> → List<Workflow>)

Correct LINQ Implementation

First, normalize the filter string to lowercase to ensure consistent case-insensitive matching:

string filterLower = FilterString.ToLower();

Then, build the filtered hierarchy by iterating from the innermost layer outwards, and only retaining parent nodes if they either match the filter themselves or have child nodes that do:

var filteredCollections = AllCollections
    .Select(collection => new Collection
    {
        Name = collection.Name,
        // Filter Repos for this Collection
        Repos = collection.Repos
            .Select(repo => new Repo
            {
                Name = repo.Name,
                // Filter Workflows for this Repo
                Workflows = repo.Workflows
                    .Where(workflow => workflow.Name.ToLower().Contains(filterLower))
                    .ToList()
            })
            // Keep Repos that either match the filter OR have matching Workflows
            .Where(repo => repo.Name.ToLower().Contains(filterLower) || repo.Workflows.Any())
            .ToList()
    })
    // Keep Collections that either match the filter OR have matching Repos
    .Where(collection => collection.Name.ToLower().Contains(filterLower) || collection.Repos.Any())
    .ToList();

How This Works

Let's walk through your example where FilterString = "Copy":

  1. Workflow Layer: Only the Workflow named "Copy" in the "VisualBasic" Repo matches, so it's retained.
  2. Repo Layer: The "VisualBasic" Repo is kept because it has a matching Workflow. All other Repos are filtered out since none of their Workflows match and their names don't include "Copy".
  3. Collection Layer: CollectionB is kept because it has a retained Repo. CollectionA is filtered out entirely since none of its Repos or their Workflows match.

The final result is a List<Collection> containing only CollectionB, which contains only the "VisualBasic" Repo, which contains only the "Copy" Workflow—exactly the structure you expected.

Why Your Original Code Failed

Your original code used SelectMany twice, which flattens the nested collections into a single sequence of Workflow objects. This discards all parent context (Repo and Collection), which is why you lost the hierarchy.

Entity Class Reference

For completeness, here are the entity definitions you provided:

public class Collection {
    public string Name { get; set; }
    public List<Repo> Repos { get; set; }
}
public class Repo {
    public string Name { get; set; }
    public List<Workflow> Workflows { get; set; }
}
public class Workflow {
    public string Name { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:08:13