【问题标题】:Comparing 2 string arrays比较 2 个字符串数组
【发布时间】:2012-08-16 08:29:46
【问题描述】:

我想以最快的方式比较 2 个字符串数组
我得到了类似下面的东西。

这会是正确的做法吗。或者有没有更好的办法

            bool matching=false;
            //say templateArr is the template array and dataArr as array to be compared
            string[] templateArr = {"Dictionary_type","Translation_EN" };
            string[] dataArr = { "Dictionary_type", "Translation_EN" };

            if (templateArr.Union(dataArr).Distinct().Count() == templateArr.Count())
                matching = true;

【问题讨论】:

  • 当你说 compare 你的意思是他们必须有相同的字符串?对于您当前的示例,我会说它们是平等的。但是,如果dataArr 多了一个(比如“测试”),结果应该是什么?
  • 我认为通过比较它们来澄清你的意思会更有帮助。你想知道它们是否都包含某种元素吗?如果他们有相同数量的条目?
  • 如果它们有相同的元素,但顺序不同怎么办?例如{"Foo", "Bar"} 是否等同于 {"Bar", "Foo"}?
  • 我觉得这个方法很好,很容易上手~
  • 顺序不同也可以,但数组元素必须相等

标签: c# data-structures collections


【解决方案1】:

要测试集合是否相等,您可以使用Enumerable.SequenceEquals,如下所示。

using System.Linq;

bool AreEqual()
{
    string[] templateArr = { "Dictionary_type", "Translation_EN" };
    string[] dataArr = { "Dictionary_type", "Translation_EN" };

    return templateArr.SequenceEquals(dataArr);
}

如果要测试集合等价性(元素的顺序无关紧要),则可以使用set-equality,如下所示。

bool AreEquivalent()
{
    string[] templateArr = { "Dictionary_type", "Translation_EN" };
    string[] dataArr = { "Dictionary_type", "Translation_EN" };

    return new HashSet<string>(templateArr).SetEquals(dataArr);
}

根据 MSDN 文档,这两种情况都是在线性时间内实现的。

【讨论】:

  • 比我的好多了,+1。但他们会是bool 而不是void,对吧?
  • 在 void 方法中,我们不能返回任何东西。
【解决方案2】:

您正在创建一个union,然后只用其中一个来计算总元素。 Union 删除了重复,但我不确定这是否是最好的方法,因为这是一个相对昂贵的操作。

看看这个替代方案:

        string[] templateArr = { "Dictionary_type", "Translation_EN" };
        string[] dataArr = { "Dictionary_type", "Translation_EN" };

        bool matching = templateArr.Length == dataArr.Length ? !templateArr.Any<string>(x => !dataArr.Contains(x)) : false;

【讨论】:

  • 对于大型数组来说性能不是很好——本质上是一个嵌套循环。再说一次,它可能对小型阵列表现良好。
  • @BrankoDimitrijevic 我明白了,但是由于我们正在使用数组,您有更好的建议吗?反馈将不胜感激。
  • 是的,事先对数组进行排序或将它们放入 HashSet 中对于更大的数组来说是合理的。
  • 我更喜欢添加这个附加条件,如果 (templateArr.Length != dataArr.Length) matching=false;是的,看起来有点贵
  • @sankaras 这个条件已经存在,见三元运算符。
【解决方案3】:

根据之前的 cmets - 这个问题有点模棱两可,因为您没有阐明什么构成等效数组,但假设您将数组视为等效,如果它们包含相同数量的相同字符串(以任何顺序),之前我会求助于 HashSet(array1).SetEquals(array2);

我会尝试使用以下简单技术来确定数组是否相等:

  1. 比较长度,如果长度不同 - 返回 false 对数组进行排序,将计数器设置为 0
  2. 比较数组 [0] 元素 - 如果不同则返回 false
  3. 对下一个重复该过程,使用索引,而不是 foreach
  4. 返回真

对于大型数组使用这种方法 - 您可能会发现差异,而不是实际将数组加载到内存中或依赖散列设置整个数组,从而获得更有效的性能/内存消耗

【讨论】:

    【解决方案4】:

    假设如果它们具有相同的元素但顺序不同,则它们应被视为不相等,您可以使用SequenceEqual

    if (templateArr.SequenceEqual(dataArr))
        matching = true;
    

    如果要忽略顺序,请先对数组进行排序:

    if (templateArr.OrderBy(x => x).SequenceEqual(dataArr.OrderBy(x => x)))
        matching = true;
    

    如果您还想忽略重复项:

    if (templateArr.Distinct().OrderBy(x => x).SequenceEqual(dataArr.Distinct().OrderBy(x => x)))
        matching = true;
    

    或者(更简洁,可能更快):

    if (new HashSet<string>(templateArr).SetEquals(dataArr))
        matching = true;
    

    顺便说一句,您的代码不正确 - 在这种情况下,它将得出数组匹配的结论:

    string[] templateArr = { "Dictionary_type", "Translation_EN", "abc" };
    string[] dataArr = { "Translation_EN", "Dictionary_type", "Translation_EN" };
    
    if (templateArr.Union(dataArr).Distinct().Count() == templateArr.Count())
        matching = true;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 2019-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多