OmegaLol21
OmegaLol21

Reputation: 87

How to find difference between lists?

So I am trying to find the difference between 2 lists of type Person. This is the person class:

class Person
{
    public int Age { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person(int age, string firstName, string lastName)
    {
        this.Age = age;
        this.FirstName = firstName;
        this.LastName = lastName;
    }
}

and in my code, I create 2 variables, List<Person> list1 and List<Person> list2.

I fill list1 with the following variables:

list1.Add(new Person(20, "first1", "last1"));
list1.Add(new Person(30, "first2", "last2"));
list1.Add(new Person(40, "first3", "last3"));
list1.Add(new Person(50, "first4", "last4"));

and fill list2 with the following:

list2.Add(new Person(30, "first2", "last2"));
list2.Add(new Person(50, "first4", "last4"));

My goal is to have another list (List<Person> list3) with list1[0] and list[2] since that is what is not included in list2. I tried using list3 = list1.Except(list2).ToList(); but that just returns a copy of list1 and if i do list3 = list2.Except(list1).ToList(); it returns a copy of list2. How do I solve this? Am I using Except() right?

Upvotes: 2

Views: 100

Answers (3)

RoadRunner
RoadRunner

Reputation: 26335

You could also create a IEqualityComparer<T> class that overrides Equals() and GetHashCode():

public class PersonEqualityComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        if (ReferenceEquals(x, y))
        {
            return true;
        }

        if (x is null || y is null)
        {
            return false;
        }

        return x.Age == y.Age && 
               x.FirstName == y.FirstName && 
               x.LastName == y.LastName;
    }

    public int GetHashCode(Person obj)
    {
        if (obj == null)
        {
            return 0;
        }

        return HashCode.Combine(obj.Age, obj.FirstName, obj.LastName);
    }
}

Then pass this comparer to Except to get the difference:

var list3 = list1.Except(list2, new PersonEqualityComparer());

Full demo on dotnetfiddle.net

Upvotes: 1

Jeff
Jeff

Reputation: 982

The underlying issue here is that you need to ask yourself, what makes these objects equal? Just because you have assigned them equal property values, does NOT make them equal. For example, although list1[1] and list2[0], seem identical, they are completely different instances of the Person object. Therefore, you need a way to tell when one Person object is "equal" to another.Generate Equals and GetHashCode method overrides in Visual Studio.

This may help as well also, Overriding Equals in C#

Hope this helps, please mark this as the answer if this does. Good luck! Here is the code which works:

class Program
{
    static void Main(string[] args)
    {
        var list1 = new List<Person>();
        list1.Add(new Person(20, "first1", "last1"));
        list1.Add(new Person(30, "first2", "last2"));
        list1.Add(new Person(40, "first3", "last3"));
        list1.Add(new Person(50, "first4", "last4"));

        var list2 = new List<Person>();
        list2.Add(new Person(30, "first2", "last2"));
        list2.Add(new Person(50, "first4", "last4"));

        var list3 = list1.Except(list2).ToList();
    }
}

class Person : IEquatable<Person>
{
    public int Age { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person(int age, string firstName, string lastName)
    {
        this.Age = age;
        this.FirstName = firstName;
        this.LastName = lastName;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Person);
    }

    public bool Equals(Person otherPerson)
    {
        return otherPerson != null && this.Age == otherPerson.Age && this.FirstName == otherPerson.FirstName && this.LastName == otherPerson.LastName;
    }

    public override int GetHashCode()
    {
        return this.Age.GetHashCode() + this.FirstName.GetHashCode() + this.LastName.GetHashCode();
    }
}

Upvotes: 4

Ross Gurbutt
Ross Gurbutt

Reputation: 1029

The equality check used by Except will be ReferenceEquals (are they literally the same object instance) because this is the default way of comparing objects for equality unless specified otherwise.
If you want Except to compare your Person class by the Age, FirstName, and LastName properties then you need to override the Equals and GetHashCode methods on the Person class.

Once you've done this list1.Except(list2).ToList() should work

Upvotes: 1

Related Questions