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:
override
Equals
andGetHashCode
and use the code aboveimplement
IEquatable<YourObjectType>
and use the code aboveimplement a custom
IEqualityComparer<YourObjectType>
and use an instance of it as parameter forSequenceEqual
and the code aboveUse 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