Determine if two sequences are equal with LINQ C#
June 10, 2014 Leave a comment
Say you have two sequences of objects:
string[] bands = { "ACDC", "Queen", "Aerosmith", "Iron Maiden", "Megadeth", "Metallica", "Cream", "Oasis", "Abba", "Blur", "Chic", "Eurythmics", "Genesis", "INXS", "Midnight Oil", "Kent", "Madness", "Manic Street Preachers" , "Noir Desir", "The Offspring", "Pink Floyd", "Rammstein", "Red Hot Chili Peppers", "Tears for Fears" , "Deep Purple", "KISS"}; string[] bandsTwo = { "ACDC", "Queen", "Aerosmith", "Iron Maiden", "Megadeth", "Metallica", "Cream", "Oasis", "Abba", "Blur", "Chic", "Eurythmics", "Genesis", "INXS", "Midnight Oil", "Kent", "Madness", "Manic Street Preachers" , "Noir Desir", "The Offspring", "Pink Floyd", "Rammstein", "Red Hot Chili Peppers", "Tears for Fears" , "Deep Purple", "KISS"};
If you’d like to check whether the two sequences include the same elements then you can use the SequenceEquals LINQ operator:
bool equal = bands.SequenceEqual(bandsTwo); Console.WriteLine(equal);
This approach works fine for objects where a good built-in comparer exists. .NET can compare two strings, two integers etc. and determine whether they are equal. It’s a different story with reference types such as your custom objects:
public class Singer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int BirthYear { get; set; } } IEnumerable<Singer> singers = new List<Singer>() { new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964} , new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954} , new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954} , new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950} , new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964} }; IEnumerable<Singer> singersTwo = new List<Singer>() { new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964} , new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954} , new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954} , new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950} , new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964} }; bool singersEqual = singers.SequenceEqual(singersTwo); Console.WriteLine(singersEqual);
This will yield false as .NET doesn’t automatically know how to compare the Singer objects in a way that makes sense to you. Instead, the comparison will be based on reference equality.
This is where an overloaded version of SequenceEquals enters the scene, one where you can specify your own equality comparer:
public class DefaultSingerComparer : IEqualityComparer<Singer> { public bool Equals(Singer x, Singer y) { return x.Id == y.Id; } public int GetHashCode(Singer obj) { return obj.Id.GetHashCode(); } }
So we say that if the singer Ids are equal then the Singer objects are equal:
bool singersEqual = singers.SequenceEqual(singersTwo, new DefaultSingerComparer()); Console.WriteLine(singersEqual);
…which yields true.
You can view all LINQ-related posts on this blog here.