SJMan
SJMan

Reputation: 1607

Filtering a nested collection using linq

I have two classes, one nested within the other,

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

}

and another class car

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

from a List<Person> I would like to filter out all the cars of , say ModelName = "Corolla".

Note that the person instance should be returned, but in the nested list only the cars should be filtered out.

The below solution is working, but I am looking for a more elegant soution.

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 ;

This is just a modified version of the original problem.TIA.

Upvotes: 6

Views: 10726

Answers (6)

Giulio Molinari
Giulio Molinari

Reputation: 132

Try this:

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

Upvotes: 0

Mairaj Ahmad
Mairaj Ahmad

Reputation: 14624

Try this. You can get list of cars of a person where make is not equal to corolla by using Where clause like this

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

Yor whole code would be like this

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 ;

Upvotes: 5

Vaibhav
Vaibhav

Reputation: 2557

Here is an abridged lambda version for you:

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

Upvotes: 5

Mukesh Kalgude
Mukesh Kalgude

Reputation: 4844

You can use cross join like this

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()
            };

Upvotes: 1

Blorgbeard
Blorgbeard

Reputation: 103535

To get a list of people with Corollas removed, and leave the original list alone:

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();

If you want to edit the original list:

foreach (var person in _result)
    person.CarsOwnedByHim = 
        person.CarsOwnedByHim
        .Where(t=>t.ModelName != "Corolla")
        .ToList()

Upvotes: 1

Dallas Lones
Dallas Lones

Reputation: 76

Using linq is awesome:

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

Make sure to include the using statement for linq

You can have unlimited where clauses just add it under the first where

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

Make sure you do .ToList or .Single or .SingleOrDefault at the end to query the data, it's not queried until you call them with .ToList or something like that.

If you want to select sub models or properties you can do it in the select:

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

Upvotes: 0

Related Questions