LINQ选择所有子集合中包含字符串的所有项

本文关键字:字符串 包含 子集合 选择 LINQ | 更新日期: 2023-09-27 18:20:54

我使用jqueryui自动完成来帮助用户选择项目。从对象的子集合中选择正确的项目时遇到问题
对象结构(简化)为

public class TargetType
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<SubCategory> SubCategories { get; set; }
    public TargetType()
    {
        SubCategories = new HashSet<SubCategory>();
    }
}
public class SubCategory
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<SubTargetType> SubTargetTypes { get; set; }
    public SubCategory()
    {
        SubTargetTypes = new HashSet<SubTargetType>();
    }
}

目前,我正在使用嵌套的foreach循环进行此操作,但有更好的方法吗
当前代码:

List<SubTargetResponse> result = new List<SubTargetResponse>();
foreach (SubCategory sc in myTargetType.SubCategories)
{
    foreach (SubTargetType stt in sc.SubTargetTypes)
    {
        if (stt.Name.ToLower().Contains(type.ToLower()))
        {
            result.Add(new SubTargetResponse {
                Id = stt.Id,
                CategoryId = sc.Id,
                Name = stt.Name });
        }
    }
}

LINQ选择所有子集合中包含字符串的所有项

您可以像这个一样使用Linq

var result = myTargetType.SubCategories
                         .SelectMany(sc => sc.SubTargetTypes)
                         .Where(stt => stt.Name.ToLower().Contains(type.ToLower()))
                         .Select(stt => new SubTargetResponse {
                                        Id = stt.Id,
                                        CategoryId = sc.Id,
                                        Name = stt.Name });

上面的查询不起作用。以下内容应该有效,但我不建议这样做,因为这不会更快或更可读。

var result = myTargetType.SubCategories
                         .Select(sc => new Tuple<int, IEnumerable<SubTargetType>>
                                            (sc.Id, 
                                             sc.SubTargetTypes.Where(stt => stt.Name.ToLower().Contains(type.ToLower()))))
                         .SelectMany(tpl => tpl.Item2.Select(stt => new SubTargetResponse {
                                        Id = stt.Id,
                                        CategoryId = tpl.Item1,
                                        Name = stt.Name }));

实际上有两个不同的问题。

LINQ选择所有子集合中包含字符串的所有项目

解决方案:

(A) LINQ语法:

var result =
    (from sc in myTargetType.SubCategories
     from stt in sc.SubTargetTypes.Where(t => t.Name.ToLower().Contains(type.ToLower()))
     select new SubTargetResponse
     {
         Id = stt.Id,
         CategoryId = sc.Id,
         Name = stt.Name
     })
    .ToList();

(B) 方法语法:

var result =
    myTargetType.SubCategories.SelectMany(
        sc => sc.SubTargetTypes.Where(stt => stt.Name.ToLower().Contains(type.ToLower())),
        (sc, stt) => new SubTargetResponse
        {
             Id = stt.Id,
             CategoryId = sc.Id,
             Name = stt.Name
        })
    .ToList();

目前,我正在使用嵌套的foreach循环进行此操作,但有更好的方法吗?

好吧,这取决于你所说的"更好"是什么意思。将您的代码与LINQ解决方案进行比较,然后回答问题。我个人并不认为LINQ在这种情况下更好(除了没有大括号和不同的缩进,但有很多隐藏的垃圾),以及在这个答案中对第二个LINQ版本该怎么说——如果它比你的代码"更好",我不知道我们要去哪里。