Intersecting results of two IEnumerable classes is pretty straightforward. An extension method called Intersect is available for objects that implement the IEnumerable interface.
Overloads
Two overloads are available:
- IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second);
- IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer);
How to…
To start you need two collections you want to match. For this example we are going to create two generic lists for a custom type called City as defined below:
public class City
{
public string Name { get; set; }
public int ID { get; set; }
}
It is time to create the lists and populate them:
City city1 = new City() { ID = 1, Name = “Sao Paulo” };
City city2 = new City() { ID = 2, Name = “Toronto” };
City city3 = new City() { ID = 3, Name = “New York” };
City city4 = new City() { ID = 4, Name = “Tokyo” };
City city5 = new City() { ID = 5, Name = “Paris” };
City city6 = new City() { ID = 6, Name = “Lisbon” };
List<City> cities = new List<City>();
cities.Add(city1);
cities.Add(city2);
cities.Add(city3);
cities.Add(city4);
cities.Add(city5);
cities.Add(city6);
List<City> cities2 = new List<City>();
cities2.Add(city1);
cities2.Add(city3);
cities2.Add(city6);
To check the items both lists have in common we are going to use the Intersect extension method that will match all items that are similar and retrieve them:
IEnumerable<City> commonCities = cities.Intersect(cities2); // or
List<City> commonCities = cities.Intersect(cities2).ToList();
Let’s check the results:
Console.WriteLine(commonCities.Count()); // Output: 3
foreach (City city in commonCities)
{
Console.WriteLine(city.Name);
}
Output:
Sao Paulo
New York
Lisbon
That is a basic scenario but sometimes you will not have the same instance of the city object in the lists resulting in a match that does not retrieve any item. The workaround for that is to use the second Intersect method overload that accepts a generic IEqualityComparer object as parameter. If you haven’t worked with IEqualityComparer yet, it’s a good time to check the Tip #42. The code below defines our class that will match the cities based on its ID:
public class CityComparer : IEqualityComparer<City>
{
public bool Equals(City city1, City city2)
{
return city1.ID == city2.ID;
}
public int GetHashCode(City city)
{
return city.ID;
}
}
Let’s recreate our lists assuming we have different instances for each city in both collections:
List<City> cities = new List<City>();
cities.Add(new City() { ID = 1, Name = “Sao Paulo” });
cities.Add(new City() { ID = 2, Name = “Toronto” });
cities.Add(new City() { ID = 3, Name = “New York” });
cities.Add(new City() { ID = 4, Name = “Tokyo” });
cities.Add(new City() { ID = 5, Name = “Paris” });
cities.Add(new City() { ID = 6, Name = “Lisbon” });
List<City> cities2 = new List<City>();
cities2.Add(new City() { ID = 1, Name = “Sao Paulo” });
cities2.Add(new City() { ID = 2, Name = “Toronto” });
cities2.Add(new City() { ID = 3, Name = “New York” });
To match the collections properly we need an instance of our comparer class:
IEnumerable<City> commonCities = cities.Intersect(cities2, new CityComparer()); // or
List<City> commonCities = cities.Intersect(cities, new CityComparer()).ToList();
Let’s check the results:
Console.WriteLine(commonCities.Count()); // Output: 3
foreach (City city in commonCities)
{
Console.WriteLine(city.Name);
}
Output:
Sao Paulo
Toronto
New York
Work with IEnumerable collections is really easy since several extension methods are available for different tasks.
Enjoy it.
Leave a comment