使用 lambda 和 LINQ 在 C# 中测试两个范围内的元素是否相等
Test whether the elements in two ranges are equal in C# using a lambda and LINQ
是否有 LINQ 或 C# 方法可以帮助在 C# 中使用 lambda 和 LINQ 测试两个范围内的元素是否相等。
事实上,我有 2 个对象数组,我想检查两个数组对象上的 属性 是否相同。
在 C++ 中,有 std::equal 可以与 lambda 一起使用(示例灵感来自 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;
}
更新:另一个与我正在尝试做的很接近的 C++ 示例:
#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;
}
您可以使用 Zip
to create an IEnumerable of tuples. With All
您可以检查是否所有这些元组都满足条件:
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");
}
您可以使用 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
如果您需要比较对象属性,您有多种选择:
覆盖Equals
和GetHashCode
并使用上面的代码
实现IEquatable<YourObjectType>
并使用上面的代码
实现自定义 IEqualityComparer<YourObjectType>
并将其实例用作 SequenceEqual
和上述代码
的参数
像这样使用不同的 LINQ 查询:
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);
(其中 AreEqual
是一种比较属性的方法,您也可以内联执行此操作)
解决您编辑过的问题:
您似乎有一个类型的数组,其中包含您要比较的 属性,忽略其他属性。
此外,您要比较的 属性 的类型实现了 IEquals<T>
和 GetHashCode()
(因为它是 string
)。
在这种情况下,您可以像这样比较两个数组:
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);
在 DotNetFiddle 中试试:https://dotnetfiddle.net/NR6bog
注意:为了简洁起见,我使用 record
。当然,这也适用于正常的 class。
是否有 LINQ 或 C# 方法可以帮助在 C# 中使用 lambda 和 LINQ 测试两个范围内的元素是否相等。
事实上,我有 2 个对象数组,我想检查两个数组对象上的 属性 是否相同。
在 C++ 中,有 std::equal 可以与 lambda 一起使用(示例灵感来自 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;
}
更新:另一个与我正在尝试做的很接近的 C++ 示例:
#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;
}
您可以使用 Zip
to create an IEnumerable of tuples. With All
您可以检查是否所有这些元组都满足条件:
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");
}
您可以使用 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
如果您需要比较对象属性,您有多种选择:
覆盖
Equals
和GetHashCode
并使用上面的代码实现
IEquatable<YourObjectType>
并使用上面的代码实现自定义
的参数IEqualityComparer<YourObjectType>
并将其实例用作SequenceEqual
和上述代码像这样使用不同的 LINQ 查询:
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);
(其中 AreEqual
是一种比较属性的方法,您也可以内联执行此操作)
解决您编辑过的问题:
您似乎有一个类型的数组,其中包含您要比较的 属性,忽略其他属性。
此外,您要比较的 属性 的类型实现了 IEquals<T>
和 GetHashCode()
(因为它是 string
)。
在这种情况下,您可以像这样比较两个数组:
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);
在 DotNetFiddle 中试试:https://dotnetfiddle.net/NR6bog
注意:为了简洁起见,我使用 record
。当然,这也适用于正常的 class。