C#: Compare two List items
Tags: csharp, linq, tips
Published: 2022-06-30 04:42:47

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.

```csharp
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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpbub9gi0jbkdhtsja4x.png)
 
# Except

By using ``Except``, we can check which elements in source list are not contained in compare list.

```csharp
var source = new List<string>() { "a", "b", "c" };
var compare = new List<string>() { "b", "c", "d" };
var result = source.Except(compare);
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djl2s0yzcjbyqbjx711l.png)

# 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.

```csharp
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``.

```csharp
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``.

```csharp
var result = source.Intersect(compare, new PersonComparer());
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kyhcuwusdyvv3ac1ci6i.png)

# 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.

```csharp
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<T>

Other way to achieve the same is to have IEquatable for class itself.

```csharp
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``.

```csharp
var result = source.Intersect(compare);
```

# Summary

There are multiple ways to compare two lists which depends on our implementation.