Comparing two collections with IEquatable while using only LINQ
Asked Answered
A

1

5

This question is for educational purposes only and I can solve it easily by using for loop that returns false on first mismatch.

I am implementing IEquatable<CustomerFeedbackViewModel> on CustomerFeedbackViewModel which has a collection of QuestionViewModel that I need to compare element by element.

public class CustomerFeedbackViewModel 
{
    public List<QuestionViewModel> Questions { get; set; }

    public string PageName { get; set; }

    public string SessionId { get; set; }
}

when implementing Equals instead of using for loop I mentioned above I wanted to use TrueForAll method it would look something like below.

public bool Equals(CustomerFeedbackViewModel other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Questions.TrueForAll((o,i) => o.Equals(other.Questions.ElementAt(i))) && string.Equals(PageName, other.PageName) && string.Equals(SessionId, other.SessionId);
    }

Ofc TrueForAll does not have index and above will never fly.

How could I go around implementing comparison of two lists without using for loop but instead using linq 'oneliner'?

Alert answered 2/2, 2016 at 9:56 Comment(1)
I think you'd want List1.SequenceEqual(List2.Take(List1.Count)) to compare all elements in List1 with the corresponding elements in List2.Czarevna
H
9

Instead of comparing each question at all indexes you should use Enumerable.SequenceEqual:

return string.Equals(PageName, other.PageName) 
    && string.Equals(SessionId, other.SessionId) 
    && Questions.SequenceEqual(other.Questions);

If you don't override Equals + GethashCode in QuestionViewModel you can provide a custom IEqualityComparer<QuestionViewModel> and pass that to the SequenceEqual overload or implement IEquatable<QuestionViewModel>.

Haywood answered 2/2, 2016 at 9:59 Comment(2)
Hi Tim, there literally no way for there to be a better solution, thanks :) I just realized that I will go on rewrite spree to change all the places where I have used for loop.Alert
If not using .NET Core, it might be worth testing that the two sequences have the same count and short-cut to false otherwise. .NET Core will short-cut if the sequences both implement ICollection<T> and have different counts, but other frameworks' versions of SequenceEqual will not.Siu

© 2022 - 2024 — McMap. All rights reserved.