在C#中比较数组的最简单方法

asm*_*smo 150 .net c# arrays compare

在Java中,Arrays.equals()允许轻松比较两个基本数组的内容(所有基本类型都可以使用重载).

C#中有这样的东西吗?是否有任何"神奇"的方法来比较C#中两个数组的内容?

Qua*_*ter 228

你可以使用SequenceEqual.这适用于任何IEnumerable<T>,而不仅仅是数组.

  • @Frédéric,事实上“SequenceEqual”将首先比较长度,如果两个枚举都实现“ICollection”,请参阅https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/ Linq/SequenceEqual.cs (5认同)
  • @quinmars,这个答案是关于.Net Framework的,.Net Core在2010年还不存在。相关代码是[这里](https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs ,920)。知道这一点在 .Net Core 中发生了变化仍然是一件好事。但对于 .Net Framework 来说仍然如此。 (4认同)
  • 这只有在它们的顺序相同时才有效 (3认同)
  • `SequenceEqual` 在性能方面可能不是一个好的选择,因为它当前的实现可能会完全枚举它的一个来源,如果它们只是长度不同。对于数组,我们可以先检查 `Length` 是否相等,以避免枚举不同长度的数组以最终产生 `false`。 (2认同)

Joh*_*nan 60

LINQ中使用SequenceEqual .

int[] arr1 = new int[] { 1,2,3};
int[] arr2 = new int[] { 3,2,1 };

Console.WriteLine(arr1.SequenceEqual(arr2)); // false
Console.WriteLine(arr1.Reverse().SequenceEqual(arr2)); // true
Run Code Online (Sandbox Code Playgroud)

  • 请记住,这会抛出 null 参数,因此请确保不要假设 `new int[] {1}.SequenceEquals(null) == false` (3认同)

des*_*sco 28

此外,对于数组(和元组),您可以使用.NET 4.0中的新接口:IStructuralComparableIStructuralEquatable.使用它们不仅可以检查数组的相等性,还可以比较它们.

static class StructuralExtensions
{
    public static bool StructuralEquals<T>(this T a, T b)
        where T : IStructuralEquatable
    {
        return a.Equals(b, StructuralComparisons.StructuralEqualityComparer);
    }

    public static int StructuralCompare<T>(this T a, T b)
        where T : IStructuralComparable
    {
        return a.CompareTo(b, StructuralComparisons.StructuralComparer);
    }
}

{
    var a = new[] { 1, 2, 3 };
    var b = new[] { 1, 2, 3 };
    Console.WriteLine(a.Equals(b)); // False
    Console.WriteLine(a.StructuralEquals(b)); // True
}
{
    var a = new[] { 1, 3, 3 };
    var b = new[] { 1, 2, 3 };
    Console.WriteLine(a.StructuralCompare(b)); // 1
}
Run Code Online (Sandbox Code Playgroud)

  • 在大值类型数组上,使用这些会降低性能,因为它们当前的实现会将每个值装箱以进行比较。 (2认同)

Yul*_*mok 17

对于.NET 4.0及更高版本,您可以使用StructuralComparisons类型比较数组或元组中的元素:

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)); 
Run Code Online (Sandbox Code Playgroud)


Joh*_*iou 12

SequenceEqual 只有满足两个条件才会返回true.

  1. 它们包含相同的元素.
  2. 元素的顺序相同.

如果您只想检查它们是否包含相同的元素而不管它们的顺序如何,并且您的问题属于类型

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
}
Run Code Online (Sandbox Code Playgroud)

而且通过使用它,您也可以自动获得不同的项目.一石二鸟.

请记住,如果您执行这样的代码

var result = values2.Except(values1);
Run Code Online (Sandbox Code Playgroud)

你会得到不同的结果.

在我的情况下,我有一个数组的本地副本,并想检查是否已从原始数组中删除任何内容,所以我使用此方法.

  • 包含相同值且顺序不同的数组,只是不等于。你觉得'Demetriou'=='uoirtemeD'吗? (2认同)

Par*_*Sen 8

对于单元测试,您可以使用CollectionAssert.AreEqual而不是Assert.AreEqual.

这可能是最简单的方法.


Har*_* He 7

如果您想妥善处理null输入,而忽略项目的顺序,请尝试以下解决方案:

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;
        return array1.Count() == array2.Count() && !array1.Except(array2).Any();
    }
}
Run Code Online (Sandbox Code Playgroud)

测试代码如下:

class Program
{
    static void Main(string[] args)
    {
        int[] a1 = new int[] { 1, 2, 3 };
        int[] a2 = new int[] { 3, 2, 1 };
        int[] a3 = new int[] { 1, 3 };
        int[] a4 = null;
        int[] a5 = null;
        int[] a6 = new int[0];

        Console.WriteLine(a1.ItemsEqual(a2)); // Output: True.
        Console.WriteLine(a2.ItemsEqual(a3)); // Output: False.
        Console.WriteLine(a4.ItemsEqual(a5)); // Output: True. No Exception.
        Console.WriteLine(a4.ItemsEqual(a3)); // Output: False. No Exception.
        Console.WriteLine(a5.ItemsEqual(a6)); // Output: False. No Exception.
    }
}
Run Code Online (Sandbox Code Playgroud)


Fré*_*ric 7

假设数组相等意味着两个数组在相同的索引处具有相同的元素,则存在SequenceEqual答案IStructuralEquatable答案

但两者都有缺点,在性能方面。

SequenceEqual当数组具有不同长度时,.Net Framework 中的实现不会快捷,因此它可能会完全枚举其中一个,比较其每个元素。
这就是说,根据 .Net 风格(如 .Net5),它可能是快捷方式,请参阅此评论。所以对于一个最新的.Net项目来说,SequenceEqual应该是一个不错的选择。

IStructuralEquatable不是通用的,可能会导致每个比较值装箱。此外,它使用起来并不是很简单,并且已经需要编写一些辅助方法来隐藏它。

从性能角度来看,使用以下内容可能会更好:

bool ArrayEquals<T>(T[] first, T[] second)
{
    if (first == second)
        return true;
    if (first == null || second == null)
        return false;
    if (first.Length != second.Length)
        return false;
    for (var i = 0; i < first.Length; i++)
    {
        if (!first[i].Equals(second[i]))
            return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但当然,这也不是检查数组相等性的某种“神奇方法”。

所以目前,Arrays.equals().Net 中还没有真正与 Java 相当的东西。


ale*_*sky 6

对于某些应用程序可能会更好:

string.Join(",", arr1) == string.Join(",", arr2)
Run Code Online (Sandbox Code Playgroud)