使用LINQ过滤嵌套集合

6

我有两个类,其中一个嵌套在另一个类中,

class Person
{
    public string Name;
    public string SSN;
    public List<Car> CarsOwnedByHim;

}

还有另一个类别的车

class Car
{
    public string RegNo; 
    public string Make;
    public string ModelName;
}

从一个 List<Person> 中,我希望过滤掉所有的汽车,比如 ModelName = "Corolla"。
请注意,应该返回 person 实例,但在嵌套列表中只应过滤掉汽车。
下面的解决方案是可行的,但我正在寻找更优雅的解决方案。
List<Person> lstPersons = new List<Person>();
foreach (var person in _result)
{
    List<Car> lstCars = new List<Car>();
    foreach (var car in person)
    {
        if (car.ModelName != "Corolla")
            lstCars.Add(car);
    }
    var tempPerson = person;
    tempPerson.CarsOwnedByHim = lstCars;
    lstPersons.Add(tempPerson);

}
return lstPersons ;

这只是原问题的修改版。谢谢您的关注。


你是否意识到 var tempPerson = person; 不会复制实例?你正在替换原始 person 上的 car 列表。 - Blorgbeard
没问题,我只是在寻找一个基于 LINQ 的解决方案。这是原始问题的简化版本。 - SJMan
你是指渐进优雅还是美学优雅;因为除非你重新审视方法本身,否则前者是不可想象的。如果只是关于使用Linq,那么它与你已经分享的基本相同 - 就像下面其他人分享的一样。 - Vaibhav
寻找基于LINQ的解决方案,我在上面的评论中提到过。 - SJMan
6个回答

5

试试这个。你可以使用Where语句来获取一个人的汽车列表,其中制造商不等于科罗拉,像这样:

lstCars = person.CarsOwnedByHim.Where(x => x.ModelName.ToUpper() != "COROLLA").ToList();

你的整个代码应该像这样

List<Person> lstPersons = new List<Person>();
foreach (var person in _result)
{
    List<Car> lstCars = new List<Car>();
    lstCars=person.CarsOwnedByHim.Where(x => x.ModelName.ToUpper() != "COROLLA").ToList();
    person.CarsOwnedByHim = lstCars;
    lstPersons.Add(person);

}
return lstPersons ;

为什么你还在用 tempPerson?它和 person 是同一个对象,所以更清晰(并且完全等效)的方式是这样写:person.CarsOwnedByHim = lstCars; lstPersons.Add(person); - Blorgbeard
@Blorgbeard 你说得对,我只是展示了如何过滤列表,我会更新答案以删除这些额外的代码,谢谢。 - Mairaj Ahmad
这可能会非常低效,因为它使用了惰性加载。 - Aron

5

以下是简化版的 lambda 表达式:

persons.ForEach(p => p.CarsOwnedByHim.RemoveAll(c => c.ModelName == "Corolla"));

1
获取已移除 Corolla 的人员列表,并保留原始列表不变:
var lstPersons = (
    from p in _result
    select new Person() {
        Name = p.Name,
        SSN = p.SSN,
        CarsOwnedByHim = p.CarsOwnedByHim.Where(t=>t.ModelName != "Corolla").ToList()
    }).ToList();

如果您想编辑原始列表:
foreach (var person in _result)
    person.CarsOwnedByHim = 
        person.CarsOwnedByHim
        .Where(t=>t.ModelName != "Corolla")
        .ToList()

1
你可以像这样使用交叉连接(cross join):
var combo = from p in Person
            from c in cars.Where(t=>t.ModelName != "Corolla")
            select new
            {
                Name=p.Name,
                SSN=p.SSN,
                CarsOwnedByHim=c.ToList()
            };

0

使用linq太棒了:

List<Car> carStatus =
    (from car in person
      where car.ModelName != "Corolla"
      select car).ToList();

请确保包含linq的using语句

您可以添加无限的where子句,只需将其添加到第一个where下面即可

List<Car> carStatus =
    (from car in person
      where car.ModelName != "Corolla"
      where car.Color == "blue"
      select car).ToList();

确保在查询数据时,在结尾处使用 .ToList 或 .Single 或 .SingleOrDefault,只有在使用 .ToList 或类似方法调用它们时才会查询数据。

如果您想选择子模型或属性,可以在 select 中执行:

List<Car> carStatus =
    (from car in person
      where car.ModelName != "Corolla"
      where car.Color == "blue"
      select car.ModelName).ToList();

0

试试这个:

var cars = (from p in persons
        from c in p.CarsOwnedByHim
        where c.ModelName == "Corolla"
        select c).ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接