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

时间:2010-07-12 22:23:45

标签: c# .net arrays compare

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

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

17 个答案:

答案 0 :(得分:207)

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

答案 1 :(得分:53)

SequenceEqual中使用LINQ

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

答案 2 :(得分:27)

对于数组(和元组),您可以使用.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
}

答案 3 :(得分: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)); 

答案 4 :(得分:12)

SequenceEqual只有在满足两个条件时才会返回true。

  1. 它们包含相同的元素。
  2. 元素的顺序相同。
  3. 如果您只是想检查它们是否包含相同的元素而不管它们的顺序如何且您的问题属于

    类型
      

    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);
    

    你会得到不同的结果。

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

答案 5 :(得分:7)

对于单元测试,您可以使用CollectionAssert.AreEqual代替Assert.AreEqual

这可能是最简单的方法。

答案 6 :(得分:4)

如果您想优雅地处理<ActionBar title="Events" class="action-bar"></ActionBar> <ActivityIndicator [busy]="isLoading" [visibility]="isLoading ? 'visible' : 'collapse'" horizontalAlignment="center" verticalAlignment="center"></ActivityIndicator> <StackLayout class="page"> <ListView [items]="events" class="list-group" [class.visible]="listLoaded" *ngIf="events"> <ng-template let-item="item"> <StackLayout class="list-group-item" (tap)="viewDetails(item)"> <Label class="h3" [text]="item.nome"></Label> </StackLayout> </ng-template> </ListView> </StackLayout> 输入,并忽略项目的顺序,请尝试以下解决方案:

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();
    }
}

答案 7 :(得分:3)

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

string.Join("", arr1) == string.Join("", arr2)

答案 8 :(得分:1)

您可以使用Enumerable.Intersect

int[] array1 = new int[] { 1, 2, 3, 4,5 },
      array2 = new int[] {7,8};

if (array1.Intersect(array2).Any())
    Console.WriteLine("matched");
else
    Console.WriteLine("not matched");

答案 9 :(得分:1)

我一直在寻找以确定两组是否具有相同顺序的相同内容。这意味着,对于集合A中的每个元素,两个集合中具有该值的元素数量相等。我想考虑重复项(因此from pylfsr import LFSR # The initial state state = [0,0,0,1,0,1,0,1,0,1,1] # The LFSR polynomial use a primitive polynomail to get maximum period length poly = [5, 4, 3, 2] l = LFSR(fpoly=poly, initstate =state) message = b"This is a Test Message" ciphertext = b"" # generate all LFSR sequence allseq = l.runFullCycle() seq = "" seq_index = 0 # Convert LFSR bits into a string for x in allseq: seq += str(x) for counter in range(len(message)): ran_seq = seq[seq_index: seq_index+8] # Now encrypt by XOR convert to bytes and append to ciphertext ciphertext += bytes([int(message[counter]) ^ int(ran_seq, 2)]) seq_index += 8 # Move sequence to Next byte print(ciphertext) plaintext = b"" # Reset The LFSR sequence to start from beginning seq_index = 0 for counter in range(len(ciphertext)): ran_seq = seq[seq_index: seq_index+8] plaintext += bytes([int(ciphertext[counter]) ^ int(ran_seq, 2)]) seq_index += 8 print(plaintext) {1,2,2,3}不应被视为“相同”。)

这是我想出的(请注意,IsNullOrEmpty是另一个静态扩展方法,如果enumerable为null或具有0个元素,则返回true):

{1,2,3,3}

答案 10 :(得分:1)

检查 this thread 的答案,它将数组之一转换为 HashSet 并使用 SetEquals 与另一个数组进行比较。

答案 11 :(得分:0)

我是在视觉工作室做到的,它运作得很好;比较数据索引与索引的比较短。

private void compareButton_Click(object sender, EventArgs e)
        {
            int[] answer = { 1, 3, 4, 6, 8, 9, 5, 4, 0, 6 };
            int[] exam = { 1, 2, 3, 6, 8, 9, 5, 4, 0, 7 };

            int correctAnswers = 0;
            int wrongAnswers = 0;

            for (int index = 0; index < answer.Length; index++)
            {
                if (answer[index] == exam[index])
                {
                    correctAnswers += 1;
                }
                else
                {
                    wrongAnswers += 1;
                }
            }

            outputLabel.Text = ("The matching numbers are " + correctAnswers +
                "\n" + "The non matching numbers are " + wrongAnswers);
        }

输出将是;匹配的数字是7                     不匹配的数字是3

答案 12 :(得分:0)

元素比较?

怎么样?
public void Linq78a()
{
 int[] numbers1 = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
 int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
 bool bb = numbers.Zip(numbers1, (a, b) => (a == b)).Any(p => !p);
 if (!bb) Console.WriteLine("Lists are equal (bb)");
   else Console.WriteLine("Lists are not equal (bb)");
}

将(a == b)条件替换为a和b中要比较的任何内容。

(这结合了MSDN developer Linq samples

中的两个例子

答案 13 :(得分:0)

假定数组相等意味着两个数组在相等的索引处具有相等的元素,分别是SequenceEqual answerIStructuralEquatable answer

但从性能角度来看,两者都有缺点。

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] != second[i])
            return false;
    }
    return true;
}

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

因此,目前还没有,.Net中没有与Java Arrays.equals()等效的东西。

答案 14 :(得分:0)

此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)
            );

答案 15 :(得分:0)

如果您不想比较订单,但是想比较每个项目的计数,包括处理空值,那么我已经为此编写了扩展方法。

例如,它给出以下结果:

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;
        }
    }
}

它只枚举每个可枚举一次,但是它确实为每个枚举创建了一个字典并对其进行了一次迭代。我会对改善这一点感兴趣。

答案 16 :(得分:-1)

        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