'Test whether the elements in two ranges are equal in C# using a lambda and LINQ

Is there a LINQ or C# method that helps to test whether the elements in two ranges are equal in C# using a lambda and LINQ.

In fact, I have 2 array of objects and I want to check if a property is the same on both array objects.

In C++, there's std::equal that can used with a lambda (example inspired from https://www.cplusplus.com/reference/algorithm/equal/)

// equal algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::equal
#include <vector>       // std::vector

bool mypredicate (int i, int j) {
  return (i==j);
}

int main () {
  int myints[] = {20,40,60,80,100};               //   myints: 20 40 60 80 100
  std::vector<int>myvector (myints,myints+5);     // myvector: 20 40 60 80 100

  myvector[3]=81;                                 // myvector: 20 40 60 81 100

  // using predicate comparison:
  if ( std::equal (myvector.begin(), myvector.end(), myints, [](int i, int j){ return i % 2 == 0 && j % 2 == 0; }) )
    std::cout << "The contents of both sequences are equal.\n";
  else
    std::cout << "The contents of both sequences differ.\n";

  return 0;
}

UPDATE: another C++ example that comes close to what I am trying to do:

#include <algorithm>    // std::equal
#include <iostream>     // std::cout
#include <string>     // std::string
#include <vector>       // std::vector

using namespace std;

struct Device
{
    Device(string id) : id(id) {}
    string id;
};

int main () {
  Device mydevices[] = {Device("A1"), Device("A2")};
  std::vector<Device> myvector(mydevices,mydevices+2);

  mydevices[1].id = "B1";

  // using predicate comparison:
  if ( std::equal (myvector.begin(), myvector.end(), mydevices, [](Device i, Device j){ return i.id == j.id; }) )
    std::cout << "The contents of both sequences are equal.\n";
  else
    std::cout << "The contents of both sequences differ.\n";

  return 0;
}


Solution 1:[1]

You can use SequenceEqual:

int[] myints = {20,40,60,20,40};
IEnumerable<int> range1 = myints.Take(2);
IEnumerable<int> range2 = myints.Skip(3);
bool equalRanges = range1.SequenceEqual(range2); // true

If you need to compare object properties you have multiple options:

  1. override Equals and GetHashCode and use the code above

  2. implement IEquatable<YourObjectType> and use the code above

  3. implement a custom IEqualityComparer<YourObjectType> and use an instance of it as parameter for SequenceEqual and the code above

  4. Use a different LINQ query like this:

    YourObjectType[] myobjects = {...};
    IEnumerable<YourObjectType> range1 = myobjects.Take(2);
    IEnumerable<YourObjectType> range2 = myobjects.Skip(3);
    bool equalRanges = range1.Zip(range2, (x1, x2) => AreEqual(x1, x2)).All(b => b);
    

(where AreEqual is a method that compares the properties, you could do this inline as well)

Solution 2:[2]

You can use Zip to create an IEnumerable of tuples. With All you can check whether all of this tuples fulfill a condition:

Device[] devices1 = {new Device("A1"), new Device("A2")};
Device[] devices2 = {new Device("A1"), new Device("A2")};

if(devices1.Zip(devices2).All(x => x.Item1.ID == x.Item2.ID))
{
    Console.WriteLine("devices1 and devices2 IDs are the same");
}

Online demo: https://dotnetfiddle.net/FIFOYP

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2