使用 Linq C# 过滤(三重)嵌套集合
Filter (Triple) Nested Collection using Linq C#
我需要过滤集合列表 > Repos > Workflows 和 return 相同格式的结果
希望 example 相当清楚,如果您认为需要更多详细信息,请大声说出来。
// All classes have a property 'Name'
// Filter along the branch for any that match and return only the matching items
List<Collection> AllCollections = new List<Collection>();
Collection CollectionA = new Collection();
Collection CollectionB = new Collection();
CollectionA.Repos = new List<Repo>{new Repo{Name = "FirstRepo", Workflows = new List<Workflow>{new Workflow{Name = "CI-CD"}, new Workflow{Name = "Tests"}, new Workflow{Name = "First-Ops"}}}, new Repo{Name = "SecondRepo", Workflows = new List<Workflow>{new Workflow{Name = "CI-CD"}, new Workflow{Name = "Testing"}, new Workflow{Name = "Second-Ops"}}}, new Repo{Name = "ThirdRepo", Workflows = new List<Workflow>{new Workflow{Name = "CI-CD"}, new Workflow{Name = "Testers"}, new Workflow{Name = "Third-Ops"}}}};
CollectionB.Repos = new List<Repo>{new Repo{Name = "FronEndUI", Workflows = new List<Workflow>{new Workflow{Name = "CD"}, new Workflow{Name = "UI-Tests"}, new Workflow{Name = "first-Op"}}}, new Repo{Name = "API", Workflows = new List<Workflow>{new Workflow{Name = "CI"}, new Workflow{Name = "Testing"}, new Workflow{Name = "second-Op"}}}, new Repo{Name = "VisualBasic", Workflows = new List<Workflow>{new Workflow{Name = "Deploy"}, new Workflow{Name = "Copy"}, new Workflow{Name = "third-Op"}}}};
AllCollections.Add(CollectionA);
AllCollections.Add(CollectionB);
// Filter
string FilterString = ""; // string FilterString = "Copy" , should return AllCollections > CollectionB > Repo VisualBasic > Workflow Deploy
// Result should be List of collections > List of Repos > List of workflows
List<Collection> result = AllCollections.SelectMany(c => c.Repos.Where(r => r.Name.Contains(FilterString.ToLower())).ToList().SelectMany(w => w.Workflows.Where(w => w.Name.Contains(FilterString)))).ToList();
// Dont know how to show nested list in a table sorry
// This is returning the workflows but not the parent Repo and Repo's Parent, The Collection
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; }
}
看这里dotnetfiddle
“将序列的每个元素投射到 IEnumerable,将生成的序列展平为一个序列,并对其中的每个元素调用结果选择器函数。”
var result =
AllCollections
.SelectMany(collection => collection.Repos,
(collection, repo) => new {collection, repo})
.SelectMany(collectionAndRepo => collectionAndRepo.repo.Workflows,
(collectionAndRepo, workflow) => new {collectionAndRepo, workflow})
.Where(collectionAndRepoAndWorkflow =>
collectionAndRepoAndWorkflow.collectionAndRepo.collection.Name
.Contains(FilterString)
|| collectionAndRepoAndWorkflow.collectionAndRepo.repo.Name.Contains(
FilterString)
|| collectionAndRepoAndWorkflow.workflow.Name.Contains(FilterString))
.GroupBy(crw => crw.collectionAndRepo.collection.Name,
(collectionName, repoAndWorkflow) =>
new Collection
{
Name = collectionName,
Repos = repoAndWorkflow.GroupBy(
rw => rw.collectionAndRepo.repo.Name,
(repoName, workflows) => new Repo()
{
Name = repoName,
Workflows = workflows.Select(w => new Workflow()
{Name = w.workflow.Name}).ToList()
}).ToList()
}).ToList();
我需要过滤集合列表 > Repos > Workflows 和 return 相同格式的结果
希望 example 相当清楚,如果您认为需要更多详细信息,请大声说出来。
// All classes have a property 'Name'
// Filter along the branch for any that match and return only the matching items
List<Collection> AllCollections = new List<Collection>();
Collection CollectionA = new Collection();
Collection CollectionB = new Collection();
CollectionA.Repos = new List<Repo>{new Repo{Name = "FirstRepo", Workflows = new List<Workflow>{new Workflow{Name = "CI-CD"}, new Workflow{Name = "Tests"}, new Workflow{Name = "First-Ops"}}}, new Repo{Name = "SecondRepo", Workflows = new List<Workflow>{new Workflow{Name = "CI-CD"}, new Workflow{Name = "Testing"}, new Workflow{Name = "Second-Ops"}}}, new Repo{Name = "ThirdRepo", Workflows = new List<Workflow>{new Workflow{Name = "CI-CD"}, new Workflow{Name = "Testers"}, new Workflow{Name = "Third-Ops"}}}};
CollectionB.Repos = new List<Repo>{new Repo{Name = "FronEndUI", Workflows = new List<Workflow>{new Workflow{Name = "CD"}, new Workflow{Name = "UI-Tests"}, new Workflow{Name = "first-Op"}}}, new Repo{Name = "API", Workflows = new List<Workflow>{new Workflow{Name = "CI"}, new Workflow{Name = "Testing"}, new Workflow{Name = "second-Op"}}}, new Repo{Name = "VisualBasic", Workflows = new List<Workflow>{new Workflow{Name = "Deploy"}, new Workflow{Name = "Copy"}, new Workflow{Name = "third-Op"}}}};
AllCollections.Add(CollectionA);
AllCollections.Add(CollectionB);
// Filter
string FilterString = ""; // string FilterString = "Copy" , should return AllCollections > CollectionB > Repo VisualBasic > Workflow Deploy
// Result should be List of collections > List of Repos > List of workflows
List<Collection> result = AllCollections.SelectMany(c => c.Repos.Where(r => r.Name.Contains(FilterString.ToLower())).ToList().SelectMany(w => w.Workflows.Where(w => w.Name.Contains(FilterString)))).ToList();
// Dont know how to show nested list in a table sorry
// This is returning the workflows but not the parent Repo and Repo's Parent, The Collection
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; }
}
看这里dotnetfiddle
“将序列的每个元素投射到 IEnumerable,将生成的序列展平为一个序列,并对其中的每个元素调用结果选择器函数。”
var result =
AllCollections
.SelectMany(collection => collection.Repos,
(collection, repo) => new {collection, repo})
.SelectMany(collectionAndRepo => collectionAndRepo.repo.Workflows,
(collectionAndRepo, workflow) => new {collectionAndRepo, workflow})
.Where(collectionAndRepoAndWorkflow =>
collectionAndRepoAndWorkflow.collectionAndRepo.collection.Name
.Contains(FilterString)
|| collectionAndRepoAndWorkflow.collectionAndRepo.repo.Name.Contains(
FilterString)
|| collectionAndRepoAndWorkflow.workflow.Name.Contains(FilterString))
.GroupBy(crw => crw.collectionAndRepo.collection.Name,
(collectionName, repoAndWorkflow) =>
new Collection
{
Name = collectionName,
Repos = repoAndWorkflow.GroupBy(
rw => rw.collectionAndRepo.repo.Name,
(repoName, workflows) => new Repo()
{
Name = repoName,
Workflows = workflows.Select(w => new Workflow()
{Name = w.workflow.Name}).ToList()
}).ToList()
}).ToList();