有很多方法可以做到这一点,但我觉得我错过了一个功能或其他什么。
显然List == List
将使用Object.Equals()
并返回false
。
如果列表中的每个元素都相等并且出现在相反列表中的相同位置,那么我认为它们是相等的。我正在使用值类型,但正确实现的Data对象应该以相同的方式工作(即,我不是在寻找浅复制列表,只是内部每个对象的值是相同的)。
我尝试过搜索并且有类似的问题,但我的问题是每个元素都按照确切的顺序相等。
答案 0 :(得分:40)
Enumerable.SequenceEqual<TSource>
答案 1 :(得分:3)
邪恶的实施是
if (List1.Count == List2.Count)
{
for(int i = 0; i < List1.Count; i++)
{
if(List1[i] != List2[i])
{
return false;
}
}
return true;
}
return false;
答案 2 :(得分:3)
我把这个变化放在一起:
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;
}
我的书呆子也爬了出来,所以我对SequenceEquals进行了性能测试,这个有一点点优势。
现在,要问的问题;这个微小的,几乎可测量的性能增益是否值得将代码添加到代码库并维护它?我非常怀疑它; o)
答案 3 :(得分:2)
我敲了一个快速扩展方法:
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;
}
}
}
答案 4 :(得分:1)
可以为序列编写通用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()));
}
}
更加充实的版本:应该会有更好的表现。
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();
}
}
这有一些功能:
比较从下到上进行。在典型的用例中,最终收集的可能性更大。
可以传递IEqualityComparer<T>
作为集合中项目的比较。
答案 5 :(得分:0)
使用 linq SequenceEqual
检查序列是否相等,因为Equals方法检查引用相等性。
bool isEqual = list1.SequenceEqual(list2);
SequenceEqual()
方法将第二个I Enumerable<T>
序列作为参数,并使用目标(第一个)序列执行逐个元素的比较。如果两个序列包含相同数量的元素,并且第一个序列中的每个元素等于第二个序列中的相应元素(使用默认相等比较器),那么SequenceEqual()
returns true
。否则,将返回false
。
或者,如果您不关心元素顺序,请使用Enumerable.All
方法:
var isEqual = list1.All(list2.Contains);
第二个版本还需要对Count进行另一次检查,因为即使list2
包含的元素多于list1
,它也会返回true。