Linq has useful method to compare two lists.
Intersect
By using Intersect
, we can check which elements in source list are also contained in compare list.
var source = new List<string>() { "a", "b", "c" };
var compare = new List<string>() { "b", "c", "d" };
var result = source.Intersect(compare);
The result is below.
Except
By using Except
, we can check which elements in source list are not contained in compare list.
var source = new List<string>() { "a", "b", "c" };
var compare = new List<string>() { "b", "c", "d" };
var result = source.Except(compare);
Complex type
We can also use complex type to compare list, by specifying which property to compare. If we use Person
model for example, we cannot simply use Intersect
nor Except
. Following code result has no value.
var source = new List<Person>() { new Person("Ken", "Nakamura"), new Person("Nozomi", "Nakamura") };
var compare = new List<Person>() { new Person("Ken", "Nakamura"), new Person("Keiko", "Nakamura") };
var result = source.Intersect(compare);
Console.ReadLine();
public class Person
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
}
Use Comparer
Both method takes comparer as second argument. Let's compare by LastName
.
public class PersonComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.LastName == y.LastName;
}
public int GetHashCode(Person x)
{
return x.LastName.GetHashCode();
}
}
Pass this class instance as second argument of Intersect
.
var result = source.Intersect(compare, new PersonComparer());
Use IntersectBy
method
If we simply want to compare elements by key, then we can use IntersectBy
instead of creating comparer. Following code generates same output as using comparer.
var source = new List<Person>() { new Person("Ken", "Nakamura"), new Person("Nozomi", "Nakamura") };
var compare = new List<Person>() { new Person("Ken", "Nakamura"), new Person("Keiko", "Nakamura") };
var result = source.IntersectBy(compare.Select(x => x.LastName), x => x.LastName);
Use IEquatable
Other way to achieve the same is to have IEquatable for class itself.
public class Person: IEquatable<Person>
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public bool Equals(Person? other) => this.LastName == other?.LastName;
public override int GetHashCode() => (LastName).GetHashCode();
}
Then we can simply call Intersect
.
var result = source.Intersect(compare);
Summary
There are multiple ways to compare two lists which depends on our implementation.
Top comments (2)
Good article thanks.
This code brings Ken Nakamura not because of Intersect "Ken"+"Nakamura" but just for "Nakamura". If your source list contains "Leo"+"Nakamura" as first element, then intersect would return Leo Nakamura object.
so true. Thanks!