LINQ过滤器列表按特定术语列出

时间:2017-01-31 09:40:13

标签: c# .net linq

我知道已经讨论了很多,但是,作为LINQ的初学者,我没有设法过滤这种情况:

我有一个包含Customers

列表的Projects列表

要过滤的列表:

List<Customer> Customers {get; set;}

这是客户类:

class Customer
{
    public string Name {get; set;}
    public List<Project> Projects {get; set;}
}

这是Project class:

class Project
{
    public string Name {get; set;}
}

我想要的只是找到所有包含 ONLY 具有特定名称的项目的客户(我的应用将根据项目的名称进行过滤)。

至于现在我有这个:

Customers
    .Where(c => c.Projects.Any(p => p.Name.ToLowerInvariant().Contains(lowerCaseFilter)));

但它没有帮助,因为它将返回包含 ALL 项目的所有客户,而不仅仅是我搜索过的项目。

例如,如果我有一个包含15个客户的列表,每个客户的项目数量都是未知数量,我希望只显示那些客户,而那些符合搜索条件的客户中的项目术语

我想我在这里错过了一些东西......

3 个答案:

答案 0 :(得分:3)

如果要修改列表,则必须重新创建客户和项目:

var searchedCustomers = Customers
    .Select(c => new { 
        Customer = c,
        FilteredProjects = c.Projects
            .Where(p => string.Equals(p.Name, nameFilter, StringComparison.InvariantCultureIgnoreCase))
            .ToList()
    })
    .Where(x => x.FilteredProjects.Any())
    .Select(x => new Customer{ 
        Name = x.Customer.Name,  
        Projects = x.FilteredProjects 
    }); 

我已将String.EqualsStringComparison.InvariantCultureIgnoreCase一起使用,以避免创建小写字符串并避免某些本地化问题,例如turkish i problem。因此,您也不需要lowerCaseFilter这种方法,因此我将其命名为nameFilter

答案 1 :(得分:0)

这样的事情:

var customers = Customers
            .Select(c => new Customer() { Name = c.Name, Projects = c.Projects == null ? new List<Project>() : c.Projects.Where(p => !string.IsNullOrEmpty(p.Name) && p.Name.ToLower().Contains(lowerCaseFilter)).ToList() })
            .Where(c => c.Projects.Any())
            .ToList();

您必须创建仅包含所需项目的新Customer对象。

答案 2 :(得分:0)

我不确定你的意思

  

它不仅会返回包含所有项目的所有客户   我搜索过的那个。

我可以用两种方式解释,请澄清:

  • 您希望返回至少拥有指定名称的项目的所有客户,并从最终结果中排除不匹配的项目(a)
  • 您只想返回那些项目符合过滤条件且没有其他项目的客户(b)(换句话说,如果任何项目与过滤器不匹配,那么该客户应该无论是否有匹配的项目,都要被排除在外。)

(a)的解决方案:

Customers
  .Where(c => c.Projects.Any(p => p.Name.ToLowerInvariant().Contains(lowerCaseFilter)))
  .Select(c => new Customer
  {
    // set all other properties
    Projects = c.Projects
      .Where(p => p.Name.ToLowerInvariant().Contains(lowerCaseFiler))
      .ToList()
  });

您在此处执行的操作只是按所需值过滤结果的Projects集合。

(b)的解决方案:

Customers
  .Where(c => c.Projects.All(p => p.Name.ToLowerInvariant().Contains(lowerCaseFilter)))

这只是过滤那些仅包含与所需过滤器匹配的项目的项目的客户集合。