我创建了两个对象列表,但不能执行总计匹配值,即
var inputNodes = new List<nodes>()
{
new node() { nodeName= "D100", DataLength = 1 },
new node() { nodeName= "D101", DataLength = 1 },
new node() { nodeName= "D102", DataLength = 1 },
new node() { nodeName= "D103", DataLength = 1 },
new node() { nodeName= "D104", DataLength = 1 },
new node() { nodeName= "D105", DataLength = 1 },
new node() { nodeName = "D106", DataLength = 1 }
};
var inputNodes2 = new List<nodes>()
{
new node() { nodeName= "D100", DataLength = 1 },
new node() { nodeName= "D101", DataLength = 1 },
new node() { nodeName= "D102", DataLength = 1 },
new node() { nodeName= "D103", DataLength = 1 },
new node() { nodeName= "D104", DataLength = 1 },
new node() { nodeName= "D105", DataLength = 1 },
new node() { nodeName= "D106", DataLength = 1 }
};
我尝试使用check,var isEqual = inputNodes.SequenceEqual(inputNodes2)
,它返回false,我不想使用循环或list.select函数,对此有什么想法吗?
发布于 2022-09-08 03:18:02
在我看来,你似乎不熟悉平等的概念,以及如何将平等的定义转变为你的定义。因此,我将解释默认等式,以及如何编写一个包含您的平等思想的等式比较器。
默认情况下,对象的相等是引用相等:如果两个对象引用相同的对象,则它们是相等的:
Node A = new Node {...}
Node X = A;
Node Y = A;
对象X和Y指同一个对象,因此:
Assert(X == Y)
IEqualityComparer<Node> nodeComparer = EqualityComparer<Node>.Default;
Assert(nodeComparer.Equals(x, y));
但是,在您的示例中,inputNodes[0]
和inputNodes2[0]
不引用同一个对象。因此,它们不是相等的节点,因此SequenceEqual
将返回false。
你不想使用标准的平等比较,你想要一个特殊的比较。根据您的定义,如果节点的属性相等,则两个节点是相等的。这个平等的定义被称为“价值平等”,与“参考平等”形成对比。
因为您不想使用默认的引用等式,所以您必须自己编写等式比较器。最简单的方法是从EqualityComparer派生一个类。
public class NodeComparer : EqualityComparer<Node>
{
public static IEqualityComparer<Node> ValueComparer {get} = new NodeComparer();
public override bool Equals(Node x, Node y) {... TODO: implement}
public override int GetHashCode(node x) {... TODO: implement}
}
使用情况如下:
IEnumerable<Node> inputNodes1 = ...
IEnumerable<Node> inputNodes2 = ...
IEqualityComparer<Node> nodeComparer = NodeComparer.ValueComparer;
bool equalInputNodes = inputNodes1.SequenceEqual(inputNodes2, nodeComparer);
等于
定义依赖于--您的平等定义。你可以使用你需要的任何定义。在您的例子中,您选择了一个简单的“按值进行比较”:
public override bool Equals(Node x, Node y)
{
// The following statements are almost always the same for every equality
if (x == null) return y == null; // true if both null
if (y == null) return false; // because x not null
if (Object.ReferenceEquals(x, y)) return true; // because same object
if (x.GetType() != y.GetType()) return false; // different types
在某些情况下,这些说法可能有所不同。例如,如果您想要创建一个字符串比较器,其中空字符串等于空字符串:
string x = null;
string y = String.Empty;
IEqualityComparer<string> stringComparer = MyStringComparer.EmptyEqualsNull;
Assert(stringComparer.Equals(x, y));
或者,如果你认为教师是人,而不是在某些情况下,你可能希望当你比较一个老师和一个人,你可能不想检查类型。
但总的来说,大多数比较器将使用这四条初始行。
继续你的平等:
return x.NodeName == y.NodeName
&& x.DataLength == y.DataLength;
为未来做好准备,考虑以下几点:
private static readonly IEqualityComparer<string> nodeNameComparer = StringComparer.Default;
在你的平等方法中:
return nodeNameComparer.Equals(x.NodeName, y.NodeName)
&& x.DataLength == y.DataLength;
因此,如果将来要进行不区分大小写的字符串比较,只需更改nodeNameComparer的静态声明:
private static readonly IEqualityComparer<string> nodeNameComparer = StringComparer.OrdinalIgnoreCase;
GetHashCode
GetHashCode的目的是创建一个快速方法来分离大多数不平等的对象。如果节点有200个属性,并且您知道,如果它们的属性Id值相等,那么很可能所有其他元素都是相等的,这是非常有用的。
请注意,我使用“非常可能”。如果X有与Y相同的哈希码,则不能保证X将等于Y,但您可以确定:
如果X与Y有不同的哈希码,那么它们就不相等。
GetHashCode的唯一要求是,如果X等于Y,那么MyComparer.GetHashCode(X)等于MyComparer.GetHashCode(Y);
如果X不等于Y,那么您就不知道它们的哈希码是否会有所不同,不过如果是这样的话会更好,因为代码会更高效。
GetHashcode
应该是快速的,它不需要检查所有的东西,如果它分离了大多数元素,它可能会很方便,但是它不需要是一个完全相等的检查。
这个怎么样?
public override int GetHashCode(Node x)
{
if (x == null) return 874283; // just a number
// for HashCode only use the NodeName:
return x.NodeName.GetHashCode();
}
或者,如果在方法中对NodeName使用字符串比较器等于:
private static readonly IEqualityComparer<string> nodeNameComparer = StringComparer.OrdinalIgnoreCase;
// this comparer is used in Equals
public override int GetHashCode(Node x)
{
if (x == null) return 874283; // just a number
return nodenameComparer.GetHashCode(x.NodeName);
}
因此,如果以后将节点名的比较方法更改为CurrentCulture
,那么等于和GetHashCode都将使用适当的比较器。
Node a = new Node {nodeName= "X", DataLength = 1 };
Node b = new Node {nodeName= "X", DataLength = 1 };
Node c = new Node {nodeName= "X", DataLength = 2 };
Node d = new Node {nodeName= "Y", DataLength = 1 };
很容易看出,b等于A.c和d与a是不同的。
虽然c是不同的,但比较器将返回与a相同的哈希码。因此,GetHashCode不足以实现完全相等,但是一个好的GetHashCode将分离大多数不同的对象。
发布于 2022-09-06 20:00:24
使用如下所示的IEqualityComparer
。
class NodeComparer : IEqualityComparer<node>
{
public bool Equals(node? x, node? y)
{
if(x == null && y == null){
return true;
}
if(x == null || y == null)
{
return false;
}
return string.Equals(x.nodeName, y.nodeName) && x.DataLength == y.DataLength;
}
public int GetHashCode([DisallowNull] node obj)
{
return obj.nodeName.GetHashCode() * obj.DataLength.GetHashCode();
}
}
然后在SequenceEquals
中使用它
inputNodes.SequenceEqual(inputNodes2, new NodeComparer());
https://stackoverflow.com/questions/73629824
复制