Makhele Sabata
Makhele Sabata

Reputation: 621

C# filter a list that is in another list

In the example below, I have a list of people who have many pets. Is there a way to return the pets with an age that is > than 5, but exclude the other pets that person owns where the age is NOT > 5 years

Example: If a person has 2 pets one is 6 years, the other is 2 years, then return that person and the 6-year-old pet, and EXCLUDE the 2-year-old pet from the list.

class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
}
class Person
{
    public string LastName { get; set; }
    public Pet[] Pets { get; set; }
}

public static void AllEx2()
{
    List<Person> people = new List<Person>
        { new Person { LastName = "Haas",
                       Pets = new Pet[] { new Pet { Name="Barley", Age=10 },
                                          new Pet { Name="Boots", Age=14 },
                                          new Pet { Name="Whiskers", Age=6 }}},
          new Person { LastName = "Fakhouri",
                       Pets = new Pet[] { new Pet { Name = "Snowball", Age = 1}}},
          new Person { LastName = "Antebi",
                       Pets = new Pet[] { new Pet { Name = "Belle", Age = 8} }},
          new Person { LastName = "Philips",
                       Pets = new Pet[] { new Pet { Name = "Sweetie", Age = 2},
                                          new Pet { Name = "Rover", Age = 13}} }
        };

    people.ForEach(person=>
        {

            person.Pets.Where(pet => pet.Age > 5);
        });
}

Upvotes: 0

Views: 126

Answers (4)

Amal Ps
Amal Ps

Reputation: 713

I think this might solve your problem. Try something like this

class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
}
class Person
{
    public string LastName { get; set; }
    public Pet[] Pets { get; set; }
}

public static void AllEx2()
{
    List<Person> people = new List<Person>
        { new Person { LastName = "Haas",
                       Pets = new Pet[] { new Pet { Name="Barley", Age=10 },
                                          new Pet { Name="Boots", Age=14 },
                                          new Pet { Name="Whiskers", Age=6 }}},
          new Person { LastName = "Fakhouri",
                       Pets = new Pet[] { new Pet { Name = "Snowball", Age = 1}}},
          new Person { LastName = "Antebi",
                       Pets = new Pet[] { new Pet { Name = "Belle", Age = 8} }},
          new Person { LastName = "Philips",
                       Pets = new Pet[] { new Pet { Name = "Sweetie", Age = 2},
                                          new Pet { Name = "Rover", Age = 13}} }
        };

    people.ForEach(person=>
        {
            // create an array with the result and reassign it to the respt array
           var pets = person.Pets.Where(pet => pet.Age > 5).ToArray();
           person.Pets = pets;
        });
}

This SO Question may be the reason. Please go through it. You will get an idea why this doesn't filter the values in your loop

Upvotes: 1

Jamiec
Jamiec

Reputation: 136074

If you create a function do do the predicate part of a Where linq query you can resuse this for both filtering the Person objects and also getting the required list of pets

Func<Pet,bool> petsOver5 = (Pet p) => p.Age > 5;

and then

var peopleWithPetsOver5 = people.Where(p => p.Pets.Any(petsOver5));
foreach(var person in peopleWithPetsOver5)
{
    Console.WriteLine($"Here are {person.LastName}'s pets over 5:");
    foreach(var pet in person.Pets.Where(petsOver5))
    {
        Console.WriteLine($"\t{pet.Name} who is age {pet.Age}");
    }
}

Live example: https://rextester.com/WUVVE89613

Upvotes: 0

gcores
gcores

Reputation: 12656

I would change the foreach section to:

people.ForEach(person=>
{
    // Get all pets for this person that are older than 5
    IEnumerable<Pet> pets = person.Pets.Where(pet => pet.Age > 5);

    // If this person has any
    if(pets.Count() != 0) 
    {
        Console.WriteLine(person.LastName);
        foreach(var p in pets)
        {
            Console.WriteLine(p.Name);
        }
    }
        
});

Upvotes: 0

Rob
Rob

Reputation: 10248

You either need to re-assign the where clause back to person.Pets (would permanently lose/remove any <= 5 pets though):

person.Pets = person.Pets.Where(pet => pet.Age > 5);

Store it locally:

var pets = person.Pets.Where(pet => pet.Age > 5);

And then iterate the local variable:

foreach(var p in pets)

Or foreach it inline instead:

foreach(var p in person.Pets.Where(pet => pet.Age > 5))

Upvotes: 0

Related Questions