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

Time:02-23

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;
}

CodePudding user response:

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)

CodePudding user response:

Addressing your edited question:

It appears that you have arrays of a type which has a property that you want to compare, ignoring other properties.

Furthermore, the type of the property that you want to compare implements IEquals<T> and GetHashCode() (because it's a string).

In this case, you can compare the two arrays like so:

using System;
using System.Linq;

static class Program
{
    public static void Main()
    {
        TestClass[] a1 = { new ("1", 1), new ("2", 2), new ("3", 3) };
        TestClass[] a2 = { new ("1", 2), new ("2", 3), new ("3", 4) };

        bool propertiesAreEqual = 
            a1.Select(element => element.PropertyToCompare)
            .SequenceEqual(
                a2.Select(element => element.PropertyToCompare));

        Console.WriteLine(propertiesAreEqual); // True
    }
}

record TestClass(string PropertyToCompare, int SomeOtherProperty);

Try it in DotNetFiddle: https://dotnetfiddle.net/NR6bog

Note: I'm just using record for brevity. This also works with a normal class, of course.

CodePudding user response:

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

  • Related