【问题标题】:Compare two .NET Array objects比较两个 .NET Array 对象
【发布时间】:2010-10-03 23:00:28
【问题描述】:

我正在尝试比较两个 .NET 数组。这是一个比较字节数组的明显实现:

bool AreEqual(byte[] a, byte[] b){
    if(a.Length != b.Length)
        return false;
    for(int i = 0; i < a.Length; i++)
        if(a[i] != b[i])
            return false;

    return true;
}

可以看到更精细的方法here(通过 Google)。

  1. 什么是最简单的方法(使用少 代码但可读)比较两个 .NET 数组?
  2. 什么是最有效的方法 比较两个 .NET 数组?

【问题讨论】:

  • 如果它们的引用相等,您也可以添加一个提前退出。

标签: .net arrays


【解决方案1】:

你可以使用SequenceEqual:

string[] a = { "1", "2", "3" };
string[] b = { "1", "2", "3" };

bool areEqual = a.SequenceEqual(b); // true


string[] c = { "1", "2", "5" };
areEqual = a.SequenceEqual(c);      // false

【讨论】:

  • 这个page 有一些性能信息,并声称SequenceEqual 比使用循环的自定义实现慢大约10 倍。我想知道为什么。
  • SequenceEqual方法默认不可用,必须使用System.Linq。很高兴知道以防您感到困惑(就像我一样)。
【解决方案2】:

Kathy 的方法对我来说似乎很好。我个人允许明确指定比较器:

bool AreEqual<T>(T[] a, T[] b)
{
    return AreEqual(a, b, EqualityComparer<T>.Default);
}

bool AreEqual<T>(T[] a, T[] b, IEqualityComparer<T> comparer)
{
    // Handle identity comparison, including comparing nulls
    if (a == b)
    {
        return true;
    }

    if (a == null || b == null)
    {
        return false;
    }

    if(a.Length != b.Length)
    {
        return false;
    }

    for(int i = 0; i < a.Length; i++)
    {
        if(!comparer.Equals(a[i], b[i]))
        {
            return false;
        }
    }
    return true;
}

CMS 提到的 SequenceEqual 很好,但由于它的通用性超过 IEnumerable&lt;T&gt;,我认为如果长度不相等,它就不能“早出”。 (它可能会检查实现 IList 的两个序列,以直接检查 Count。)您可以再概括一点,以使用 IList&lt;T&gt;

bool AreEqual<T>(IList<T> a, IList<T> b, IEqualityComparer<T> comparer)
{
    if(a.Count != b.Count)
    {
        return false;
    }
    for(int i = 0; i < a.Count; i++)
    {
        if(!comparer.Equals(a[i], b[i]))
        {
            return false;
        }
    }
    return true;
}

直接数组版本可能是最有效的 - 添加通用性和抽象性通常会影响性能,尽管它是否显着将取决于您的应用程序。

【讨论】:

  • 上面的代码sn-ps不应该有if (!comparer.Equals(a[i], b[i]) return false吗?我是不是刚刚在我的宇宙中发现了异常:)
  • 在第二个 'if' 语句之后还需要一个右括号。
  • @Jon 你能解释一下明确指定比较器有什么好处吗?
  • @Sandeep:假设您希望能够比较两个字符串数组是否相等,但使用不区分大小写的比较,所以{"FOO", "BAR"} 等于{"foo", "bar"}
  • 第二个代码sn-p不应该也用!comparer.Equals(...)吗?
【解决方案3】:

随着 .NET 4 的出现,您可以使用 .NET 数组的显式实现接口 IStructuralEquatable 提供的方法 Equals()。那么代码可能如下所示(我重写了 CMS 的示例):

string[] a = { "1", "2", "3" };
string[] b = { "1", "2", "3" };
bool result = ((IStructuralEquatable)a).Equals(b, StructuralComparisons.StructuralEqualityComparer);
// result evaluates to true.

(IStructuralEquatable 也在元组中实现(也是 .NET 4 中的新功能)。)

【讨论】:

  • 或使用StructuralComparisons.StructuralEqualityComparer.Compare(a,b)
  • 谢谢你,克里斯!你的解决方案比我的有一个重要的好处:它可以识别空值。
【解决方案4】:

也许是这样的?

static bool AreEqual<T>(T[] a, T[] b) 
{
    bool areEqual = false ;
    T[] result = a.Intersect(b.AsEnumerable()).ToArray();
    areEqual = (result.Length == a.Length) && (result.Length == b.Length);
    return areEqual;
}

不过,我不确定这对性能的影响。

编辑

考虑到 Jon 建议的修订版本:

    static bool AreEqual<T>(T[] a, T[] b) 
    {
        return a.SequenceEqual(b);
    }

【讨论】:

  • 如果您可以使用 LINQ 并且不介意直接使用数组(以及早期使用不同长度)带来的性能损失,SequenceEqual 是前进的方向。
  • 当存在重复项时,此解决方案会失败:{ 1, 1, 1} = { 1, 1, 1} 返回 false。它也不考虑排序:{ 1, 2} != {2, 1} 返回 true。
  • "{ 1, 2} != {2, 1} 返回 true" 应该表示考虑了排序 对吧?
  • 我是说订购应该考虑,但不是。这两个数组应该被视为不同,但此答案中 AreEqual 的原始版本返回 true。很抱歉造成混乱。
  • 如果你想检查 2 个集合是否具有相同的唯一值,那么可以使用类似:return (new HashSet&lt;T&gt;(a)).SetEquals(b);(这会忽略顺序并且不在乎相同的值是否存在不止一次。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-26
  • 2019-08-02
  • 2014-01-26
  • 2012-08-17
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多