Search code examples
c#linq

Check if two lists are equal


I have a class as follows:

public class Tag {
    public Int32 Id { get; set; }
    public String Name { get; set; }
}

And I have two lists of tag:

List<Tag> tags1;
List<Tag> tags2;

I used LINQ's select to get the Ids of each tags list. And then:

List<Int32> ids1 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids2 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids3 = new List<Int32> { 2, 1, 3, 4 };
List<Int32> ids4 = new List<Int32> { 1, 2, 3, 5 };
List<Int32> ids5 = new List<Int32> { 1, 1, 3, 4 };

ids1 should be equal to ids2 and ids3 ... Both have the same numbers.

ids1 should not be equal to ids4 and to ids5 ...

I tried the following:

var a = ints1.Equals(ints2);
var b = ints1.Equals(ints3);

But both give me false.

What is the fastest way to check if the lists of tags are equal?

UPDATE

I am looking for POSTS which TAGS are exactly the same as the TAGS in a BOOK.

IRepository repository = new Repository(new Context());

IList<Tags> tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } };

Book book = new Book { Tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } } };

var posts = repository
  .Include<Post>(x => x.Tags)
  .Where(x => new HashSet<Int32>(tags.Select(y => y.Id)).SetEquals(book.Tags.Select(y => y.Id)))
  .ToList();

I am using Entity Framework and I get the error:

An exception of type 'System.NotSupportedException' occurred in mscorlib.dll but was not handled in user code

Additional information: LINQ to Entities does not recognize the method 'Boolean SetEquals(System.Collections.Generic.IEnumerable`1[System.Int32])' method, and this method cannot be translated into a store expression.

How do I solve this?


Solution

  • Use SequenceEqual to check for sequence equality because Equals method checks for reference equality.

    var a = ints1.SequenceEqual(ints2);
    

    Or if you don't care about elements order use Enumerable.All method:

    var a = ints1.All(ints2.Contains);
    

    The second version also requires another check for Count because it would return true even if ints2 contains more elements than ints1. So the more correct version would be something like this:

    var a = ints1.All(ints2.Contains) && ints1.Count == ints2.Count;
    

    In order to check inequality just reverse the result of All method:

    var a = !ints1.All(ints2.Contains)