In Byte-Sized #3 we are looking about the Intersect()
method. Thats finds the common elements between two collections.
What is Intersect()
In LINQ , Intersect()
is an operator to perform a set intersection of two sequences. It returns a new sequence that contains the elements common to both sequences, in other words, the elements that appear in both sequences.
The syntax for using the Intersect operator in LINQ is as follows:
var commonElements = sequence1.Intersect(sequence2);
Today I am going to introduce how to play with Intersect and the new syntaxes of this.
Simple sequences
You can use the Intersect operator to find the common elements between the two lists as follows:
List<int> list1 = new List<int> { 1, 2, 3, 4, 5 };
List<int> list2 = new List<int> { 3, 4, 5, 6, 7 };
var list1list2Common = list1.Intersect(list2);
foreach (var item in list1list2Common)
{
Console.WriteLine(item);
}
/*
3
4
5
*/
The result will be a new sequence containing the elements { 3, 4, 5 }, which are the elements that are common to both lists.
complex object sequences
Suppose you have a class Person that represents a person with a name and an age.
public class Person : IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
}
And I used below List3 and List4 for describe examples
var list3 = new List<Person>
{
new Person { Name = "Alice", Age = 25 },
new Person { Name = "Bob", Age = 30 },
new Person { Name = "Charlie", Age = 35 },
new Person { Name = "Eve", Age = 50 }
};
var list4 = new List<Person>
{
new Person { Name = "Bob", Age = 30 },
new Person { Name = "David", Age = 35 },
new Person { Name = "Eve", Age = 40 }
};
1. Using IEquatable<T>
To use Intersect with complex object lists, you can implement the IEquatable<T>
interface on the class that represents the objects in the lists. The IEquatable<T>
interface defines the Equals()
method, which is used by the Intersect operator to compare the objects in the lists.
public class Person : IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
// override Equals method
public bool Equals(Person other)
{
if (other == null) return false;
return (this.Name == other.Name
&& this.Age == other.Age);
}
}
//...
var list3list4CommonEquatable = list3.Intersect(list4);
foreach (var item in list3list4CommonEquatable)
{
Console.WriteLine(item.Name); // Bob
}
Here is the Sample code, and As the Name and Age, Bob is the common element in the sequence.
2. Using IEqualityComparer<T>
You can also use the Intersect
operator on complex object lists by providing a custom IEqualityComparer<T>
implementation that defines how to compare the objects in the lists.
I have created a custom PersonComparer
class that implements the IEqualityComparer<Person>
interface. This custom comparer defines how to compare two Person
objects by implementing the Equals
method, and how to calculate the hash code of a Person
object by implementing the GetHashCode
method.
public class PersonComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (x == null || y == null) return false;
return (x.Name == y.Name && x.Age == y.Age);
}
public int GetHashCode(Person obj)
{
if (obj == null) return 0;
return obj.Name.GetHashCode()
^ obj.Age.GetHashCode();
}
}
To use the Intersect
operator on a list of Person
objects, you can create two lists and a new instance of PersonComparer
, and then call the Intersect
method with the two lists and the custom comparer.
var comparer = new PersonComparer();
var commonPeople = list1.Intersect(list2, comparer);
IntersectBy() - New Implementation
Exisiting method Intersect
has been powered up by these new methods which can take a selector function to operate. This IntersectBy()
was introduced with .NET 6 new linq features.
If we simply want to compare elements by key (Name), then we can use IntersectBy
instead of creating comparer. Following code generates same output as using comparer.
// in this name is the key
var list3list4CommonSingleProperty
= list3.IntersectBy(
list4.Select(o => o.Name),
x =>x.Name);
foreach (var item in list3list4CommonSingleProperty)
{
Console.WriteLine(item.Name);
}
//Bob
//Eve
Here is an example of the showcase of how multiple properties can process like comparer. Here Age and Name are considered equality properties.
var list3list4CommonMultipleProperties
= list3
.IntersectBy(list4.Select(o => new { name = o.Name, age = o.Age}),
x => new {name = x.Name, age= x.Age});
foreach (var item in list3list4CommonMultipleProperties)
{
Console.WriteLine(item.Name);
}
Conclusion
Intersect
operator in LINQ is a powerful tool that allows developers to find the common elements between two collections. It can be used to simplify complex operations and save developers time and effort.The
IntersectBy
is more powerful which can take a selector function to operate.Resources
Demo Project
There is a demo project you can check out over on GitHub with the examples for Intersect()
and IntersectBy()
.