在Java中,arrays .equals()允许轻松地比较两个基本数组的内容(重载可用于所有基本类型)。
c#中有这样的东西吗?在c#中是否存在比较两个数组内容的“神奇”方法?
在Java中,arrays .equals()允许轻松地比较两个基本数组的内容(重载可用于所有基本类型)。
c#中有这样的东西吗?在c#中是否存在比较两个数组内容的“神奇”方法?
当前回答
对于。net 4.0及更高版本,您可以通过使用structuralcompare类型比较数组或元组中的元素:
object[] a1 = { "string", 123, true };
object[] a2 = { "string", 123, true };
Console.WriteLine (a1 == a2); // False (because arrays is reference types)
Console.WriteLine (a1.Equals (a2)); // False (because arrays is reference types)
IStructuralEquatable se1 = a1;
//Next returns True
Console.WriteLine (se1.Equals (a2, StructuralComparisons.StructuralEqualityComparer));
其他回答
如果您不想比较顺序,但确实想比较每一项的计数,包括处理空值,那么我为此编写了一个扩展方法。
例如,它给出了以下结果:
new int?[]{ }.IgnoreOrderComparison(new int?{ }); // true
new int?[]{ 1 }.IgnoreOrderComparison(new int?{ }); // false
new int?[]{ }.IgnoreOrderComparison(new int?{ 1 }); // false
new int?[]{ 1 }.IgnoreOrderComparison(new int?{ 1 }); // true
new int?[]{ 1, 2 }.IgnoreOrderComparison(new int?{ 2, 1 }); // true
new int?[]{ 1, 2, null }.IgnoreOrderComparison(new int?{ 2, 1 }); // false
new int?[]{ 1, 2, null }.IgnoreOrderComparison(new int?{ null, 2, 1 }); // true
new int?[]{ 1, 2, null, null }.IgnoreOrderComparison(new int?{ null, 2, 1 }); // false
new int?[]{ 2 }.IgnoreOrderComparison(new int?{ 2, 2 }); // false
new int?[]{ 2, 2 }.IgnoreOrderComparison(new int?{ 2, 2 }); // true
代码如下:
public static class ArrayComparisonExtensions
{
public static bool IgnoreOrderComparison<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) =>
IgnoreOrderComparison(first, second, EqualityComparer<TSource>.Default);
public static bool IgnoreOrderComparison<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
var a = ToDictionary(first, out var firstNullCount);
var b = ToDictionary(second, out var secondNullCount);
if (a.Count != b.Count)
return false;
if (firstNullCount != secondNullCount)
return false;
foreach (var item in a)
{
if (b.TryGetValue(item.Key, out var count) && item.Value == count)
continue;
return false;
}
return true;
Dictionary<TSource, int> ToDictionary(IEnumerable<TSource> items, out int nullCount)
{
nullCount = 0;
var result = new Dictionary<TSource, int>(comparer);
foreach (var item in items)
{
if (item is null)
nullCount++;
else if (result.TryGetValue(item, out var count))
result[item] = count + 1;
else
result[item] = 1;
}
return result;
}
}
}
它只枚举每个枚举对象一次,但它确实为每个枚举对象创建了一个字典,并迭代这些字典一次。我对如何改善这一点很感兴趣。
int[] a = { 2, 1, 3, 4, 5, 2 };
int[] b = { 2, 1, 3, 4, 5, 2 };
bool ans = true;
if(a.Length != b.Length)
{
ans = false;
}
else
{
for (int i = 0; i < a.Length; i++)
{
if( a[i] != b[i])
{
ans = false;
}
}
}
string str = "";
if(ans == true)
{
str = "Two Arrays are Equal";
}
if (ans == false)
{
str = "Two Arrays are not Equal";
}
//--------------Or You can write One line of Code-------------
var ArrayEquals = a.SequenceEqual(b); // returns true
SequenceEqual只在满足两个条件时才返回true。
它们包含相同的元素。 元素的顺序是一样的。
如果您只想检查它们是否包含相同的元素,而不管它们的顺序如何,那么您的问题属于
values2是否包含values1中包含的所有值?
可以使用LINQ扩展方法Enumerable。Except,然后检查结果是否有任何值。这里有一个例子
int[] values1 = { 1, 2, 3, 4 };
int[] values2 = { 1, 2, 5 };
var result = values1.Except(values2);
if(result.Count()==0)
{
//They are the same
}
else
{
//They are different
}
通过这个你也可以自动得到不同的项目。一石二鸟。
请记住,如果像这样执行代码
var result = values2.Except(values1);
你会得到不同的结果。
在我的例子中,我有一个数组的本地副本,想要检查是否有任何东西已经从原始数组中删除,所以我使用这个方法。
如果你想优雅地处理空输入,并忽略项目的顺序,尝试以下解决方案:
static class Extensions
{
public static bool ItemsEqual<TSource>(this TSource[] array1, TSource[] array2)
{
if (array1 == null && array2 == null)
return true;
if (array1 == null || array2 == null)
return false;
if (array1.Count() != array2.Count())
return false;
return !array1.Except(array2).Any() && !array2.Except(array1).Any();
}
}
测试代码如下所示:
public static void Main()
{
int[] a1 = new int[] { 1, 2, 3 };
int[] a2 = new int[] { 3, 2, 1 };
int[] a3 = new int[] { 1, 3 };
Console.WriteLine(a1.ItemsEqual(a2)); // Output: True.
Console.WriteLine(a2.ItemsEqual(a3)); // Output: False.
Console.WriteLine(a3.ItemsEqual(a2)); // Output: False.
int[] a4 = new int[] { 1, 1 };
int[] a5 = new int[] { 1, 2 };
Console.WriteLine(a4.ItemsEqual(a5)); // Output: False
Console.WriteLine(a5.ItemsEqual(a4)); // Output: False
int[] a6 = null;
int[] a7 = null;
int[] a8 = new int[0];
Console.WriteLine(a6.ItemsEqual(a7)); // Output: True. No Exception.
Console.WriteLine(a8.ItemsEqual(a6)); // Output: False. No Exception.
Console.WriteLine(a7.ItemsEqual(a8)); // Output: False. No Exception.
}
这个LINQ解决方案是有效的,不知道它在性能上如何与SequenceEquals相比。但是它处理不同的数组长度,. all将在不遍历整个数组的情况下,在第一个不相等的项上退出。
private static bool arraysEqual<T>(IList<T> arr1, IList<T> arr2)
=>
ReferenceEquals(arr1, arr2) || (
arr1 != null && arr2 != null &&
arr1.Count == arr2.Count &&
arr1.Select((a, i) => arr2[i].Equals(a)).All(i => i)
);