在 C# 中检查两个 List<T> 列表是否相等的最佳方法是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/876508/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to check two List<T> lists for equality in C#
提问by Spence
There are many ways to do this but I feel like I've missed a function or something.
有很多方法可以做到这一点,但我觉得我错过了一个功能或其他东西。
Obviously List == List
will use Object.Equals()
and return false
.
显然List == List
会使用Object.Equals()
并返回false
。
If every element of the list is equal and present in the same location in the opposite list then I would consider them to be equal. I'm using value types, but a correctly implemented Data object should work in the same fashion (i.e I'm not looking for a shallow copied list, only that the valueof each object within is the same).
如果列表中的每个元素都相等并且出现在相反列表中的相同位置,那么我会认为它们是相等的。我正在使用值类型,但正确实现的 Data 对象应该以相同的方式工作(即我不是在寻找浅复制列表,只是其中每个对象的值是相同的)。
I've tried searching and there are similar questions, but my question is an equality of every element, in an exact order.
我试过搜索,也有类似的问题,但我的问题是每个元素都按精确顺序相等。
回答by Spence
Evil implementation is
邪恶的执行是
if (List1.Count == List2.Count)
{
for(int i = 0; i < List1.Count; i++)
{
if(List1[i] != List2[i])
{
return false;
}
}
return true;
}
return false;
回答by Luke Schafer
I knocked up a quick extension method:
我敲了一个快速扩展的方法:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static bool Matches<T>(this List<T> list1, List<T> list2)
{
if (list1.Count != list2.Count) return false;
for (var i = 0; i < list1.Count; i++)
{
if (list1[i] != list2[i]) return false;
}
return true;
}
}
}
回答by Fredrik M?rk
I put together this variation:
我把这个变化放在一起:
private bool AreEqual<T>(List<T> x, List<T> y)
{
// same list or both are null
if (x == y)
{
return true;
}
// one is null (but not the other)
if (x== null || y == null)
{
return false;
}
// count differs; they are not equal
if (x.Count != y.Count)
{
return false;
}
for (int i = 0; i < x.Count; i++)
{
if (!x[i].Equals(y[i]))
{
return false;
}
}
return true;
}
The nerd in me also crawled out so I did a performance test against SequenceEquals, and this one has a slight edge.
我的书呆子也爬了出来,所以我对 SequenceEquals 进行了性能测试,这个测试略有优势。
Now, the question to ask; is this tiny, almost measurable performance gain worth adding the code to the code base and maintaining it? I very much doubt it ;o)
现在,要问的问题;这种微小的、几乎可衡量的性能提升是否值得将代码添加到代码库中并对其进行维护?我非常怀疑它;o)
回答by nawfal
One can write a general purpose IEqualityComparer<T>
for sequences. A simple one:
可以IEqualityComparer<T>
为序列编写一个通用目的。一个简单的:
public class SequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>>
{
public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
{
return x.SequenceEqual(y);
}
public int GetHashCode(IEnumerable<T> obj)
{
return unchecked(obj.Aggregate(397, (x, y) => x * 31 + y.GetHashCode()));
}
}
A more fleshed out version: which should be better performing.
一个更充实的版本:它应该表现更好。
public class SequenceEqualityComparer<T> : EqualityComparer<IEnumerable<T>>,
IEquatable<SequenceEqualityComparer<T>>
{
readonly IEqualityComparer<T> comparer;
public SequenceEqualityComparer(IEqualityComparer<T> comparer = null)
{
this.comparer = comparer ?? EqualityComparer<T>.Default;
}
public override bool Equals(IEnumerable<T> x, IEnumerable<T> y)
{
// safer to use ReferenceEquals as == could be overridden
if (ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
var xICollection = x as ICollection<T>;
if (xICollection != null)
{
var yICollection = y as ICollection<T>;
if (yICollection != null)
{
if (xICollection.Count != yICollection.Count)
return false;
var xIList = x as IList<T>;
if (xIList != null)
{
var yIList = y as IList<T>;
if (yIList != null)
{
// optimization - loops from bottom
for (int i = xIList.Count - 1; i >= 0; i--)
if (!comparer.Equals(xIList[i], yIList[i]))
return false;
return true;
}
}
}
}
return x.SequenceEqual(y, comparer);
}
public override int GetHashCode(IEnumerable<T> sequence)
{
unchecked
{
int hash = 397;
foreach (var item in sequence)
hash = hash * 31 + comparer.GetHashCode(item);
return hash;
}
}
public bool Equals(SequenceEqualityComparer<T> other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return this.comparer.Equals(other.comparer);
}
public override bool Equals(object obj)
{
return Equals(obj as SequenceEqualityComparer<T>);
}
public override int GetHashCode()
{
return comparer.GetHashCode();
}
}
This has a few features:
这有几个特点:
The comparison is done from bottom to top. There is more probability for collections differing at the end in typical use-cases.
An
IEqualityComparer<T>
can be passed to base the comparison for items in the collection.
比较是从下到上进行的。在典型的用例中,集合最终不同的可能性更大。
一个
IEqualityComparer<T>
可以传递到基地集合中的项目进行比较。
回答by Hasan Fathi
Use linqSequenceEqual
to check for sequence equality because Equals method checks for reference equality.
使用linqSequenceEqual
检查序列相等性,因为 Equals 方法检查引用相等性。
bool isEqual = list1.SequenceEqual(list2);
The SequenceEqual()
method takes a second IEnumerable<T>
sequence as a parameter, and performs a comparison, element-by-element, with the target (first) sequence. If the two sequences contain the same numberof elements, and each element in the first sequence is equal to the corresponding element in the second sequence (using the default equality comparer) then SequenceEqual()
returns true
. Otherwise, false
is returned.
该SequenceEqual()
方法将第二个 IEnumerable<T>
序列作为参数,并与目标(第一个)序列逐个元素地进行比较。如果两个序列包含相同数量的元素,并且第一个序列中的每个元素都等于第二个序列中的对应元素(使用默认相等比较器),则SequenceEqual()
returns true
. 否则,false
被退回。
Or if you don't care about elements order use Enumerable.All
method:
或者,如果您不关心元素顺序使用Enumerable.All
方法:
var isEqual = list1.All(list2.Contains);
The second version also requires another check for Count because it would return true even if list2
contains more elements than list1
.
第二个版本还需要对 Count 进行另一次检查,因为即使list2
包含的元素多于 ,它也会返回 true list1
。