【问题标题】:How to equate the elements of two array irrespective of the order of entries无论条目的顺序如何,如何使两个数组的元素相等
【发布时间】:2009-06-15 13:50:33
【问题描述】:

我正在尝试统计两个数组,例如 myArray{a,b,c}urArray{a,b,c,c}

我想检查两个元素是否具有相同的元素,例如在上述条件下,第二个数组urArray 有一个额外的'c'。

并且代码应该能够等同于两组数组如果它们具有相同的元素并且元素的顺序无关紧要。只是两个数组应该有相同的元素,即如果一个有两个'c',另一个也应该有两个'c',否则条件为假。

所以我做的是:

char[] myArray = new char[] {'a','b','c','c'};
char[] urArray = new char[] { 'a', 'b', 'c' ,'a'};
List<char> tmp2 = new List<char>(urArray);

for (int i = 0; i < myArray.Length; ++i)
{
    for (int j = 0; j < urArray.Length; ++j)
    {
        if (myArray[i] == urArray[j])
        {

            Console.WriteLine(urArray[j] + "--> " + "urArray"+"  myArray"+"--> "+myArray[i]);
            tmp2.Remove(urArray[j]);

            urArray = tmp2.ToArray();

        }
        else if (myArray[i] != urArray[j])
        {
            Console.WriteLine(myArray[i] + "--> " + "myArray" + "  urArray" + "--> " + urArray[j]);
        }
    }
}

但不知道如何显示数组是否具有相同的元素...

我怎样才能做到这一点?

【问题讨论】:

标签: c# arrays comparison equality


【解决方案1】:

这里有一些使用 linq 的 C# 代码应该可以完成这项工作,它基本上是排序/比较序列形式的实现——这是最可靠的。此代码将对两个序列进行排序并比较它们的等价性。您可以稍微优化一下,首先检查 myArrayurArray 的长度是否相同,以避免不必要的排序。

char[] myArray = new char[] {'a','b','c','c'};
char[] urArray = new char[] { 'a', 'b', 'c' ,'a'};

var areEqual = myArray.OrderBy( x => x )
                      .SequenceEqual( urArray.OrderBy( x => x ) );

如果由于某种原因您不能(或不想)使用 linq,这里是使用 .NET 2.0 代码的等效版本:

public static bool AreEquivalentArray( char[] a, char[] b )
        {
            if (a.Length != b.Length)
                return false;

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

【讨论】:

  • 该问题被标记为“visualstudio2005”,这表明需要非 LINQ 解决方案。
  • 解决方案必须能够处理不同长度的数组,因为可能存在重复
  • 这不是我的理解,原始问题指出:“如果两组数组是否具有相同的元素,并且元素的顺序无关紧要,两个数组都应该具有相同的元素,即如果一个有两个'c',另一个也应该有两个'c',否则条件为假"
  • 我最初的解决方案就是这样做的,但我被告知这是错误的,所以我认为 jarus 想要某种形式的处理来处理重复......我可能错了哈哈
【解决方案2】:

您可以对两个数组进行排序,然后依次比较元素。如果在任何时候被比较的两个元素不同,则数组包含不同的元素。

【讨论】:

    【解决方案3】:

    这似乎与我遇到的相同问题:Comparing Two Collections for Equality

    【讨论】:

    • 为什么要在解决方案中执行这种复杂的密钥查找?为什么不只是 ContainsKey()?您的代码中有 cmets 说字典使用引用相等,但事实并非如此。如果 TKey 是值类型,则根本不存在引用相等性。你能详细说明一下吗?也许我错过了重要的一点。
    • 如果一个集合包含两个相同的集合,而另一个集合只包含一个,如果我不使用计数器进行键查找,我不会知道集合是不同的。我还提到代码是比较相等的。如果对象是引用类型(对象),则将比较它们的引用。因此,如果我有同一个对象的两个实例,它们将不相等。
    【解决方案4】:

    我建议计算两个序列的直方图之间的差异。如果无法对序列进行排序或没有有效的方法来确定序列的长度,这甚至会起作用。

    public static Boolean CompareCollections<T>(IEnumerable<T> a, IEnumerable<T> b)
    {
        Dictionary<T, Int32> histogram = new Dictionary<T, Int32>();
    
        foreach (T item in a)
        {
            Int32 count;
            if (histogram.TryGetValue(item, out count))
            {
                histogram[item]++;
            }
            else
            {
                histogram[item] = 1;
            }
        }
    
        foreach (T item in b)
        {
            Int32 count;
            if (histogram.TryGetValue(item, out count))
            {
                if (count <= 0)
                {
                    return false;
                }
    
                histogram[item]--;
            }
            else
            {
                return false;
            }
        }
    
        foreach (Int32 value in histogram.Values)
        {
            if (value != 0)
            {
                return false;
            }
        }
    
        return true;
    }
    

    如果可以得到序列的长度,检查字典中的所有值是否为零可以替换为检查相等的序列长度。

    public static Boolean CompareCollections<T>(ICollection<T> a, ICollection<T> b)
    {
        if (a.Count != b.Count)
        {
            return false;
        }
    
        Dictionary<T, Int32> histogram = new Dictionary<T, Int32>();
    
        foreach (T item in a)
        {
            Int32 count;
            if (histogram.TryGetValue(item, out count))
            {
                histogram[item]++;
            }
            else
            {
                histogram[item] = 1;
            }
        }
    
        foreach (T item in b)
        {
            Int32 count;
            if (histogram.TryGetValue(item, out count))
            {
                if (count <= 0)
                {
                    return false;
                }
    
                histogram[item]--;
            }
            else
            {
                return false;
            }
        }
    
        return true;
    }
    

    如果构建字典的成本可以忽略不计,而排序需要O(n*log(n)) 时间,则此解决方案为O(n)

    【讨论】:

      【解决方案5】:

      这是一个带有 LINQ 的单行代码:

      bool same = !array1.Except (array2).Any() && !array2.Except (array1).Any();
      

      或者,您可以在每个序列上调用 OrderBy 以按相同顺序对它们进行排序,然后使用 Enumerable.SequenceEqual 来比较它们:

      bool same = Enumerable.SequenceEqual (array1.OrderBy (n => n), array2.OrderBy (n => n));
      

      【讨论】:

      • 第一个版本是不正确的,因为它会错误地将不同大小的数组报告为等效,并且不能正确处理重复项。第二个版本是正确的。排序然后比较序列。
      • 是的——你说的很对。鉴于这个问题, except() 不会做这项工作。
      • 该问题被标记为“visualstudio2005”,这表明需要非 LINQ 解决方案。
      【解决方案6】:
      return myArray.OrderBy(c => c).SequenceEqual(urArray.OrderBy(c => c));
      

      【讨论】:

        【解决方案7】:

        如果你的数组只包含唯一元素,我会从它们中创建两个 HashSet,然后从另一个中减去一个,看看结果是否为空集。

        【讨论】:

        • 问题被标记为“visualstudio2005”。如果是这样,那么 HashSet 将不可用。
        【解决方案8】:

        如果您无法使用 LINQ,那么这应该可以解决问题:

        char[] myArray = new char[] { 'a', 'b', 'c', 'c' };
        char[] urArray = new char[] { 'a', 'b', 'c' ,'a' };
        
        Console.WriteLine(AreEqual(myArray, urArray));    // False
        
        // ...
        
        public bool AreEqual<T>(IEnumerable<T> first, IEnumerable<T> second)
        {
            Dictionary<T, int> map = new Dictionary<T, int>();
        
            foreach (T item in first)
            {
                if (map.ContainsKey(item))
                    map[item]++;
                else
                    map[item] = 1;
            }
        
            foreach (T item in second)
            {
                if (map.ContainsKey(item))
                    map[item]--;
                else
                    return false;
            }
        
            foreach (int i in map.Values)
            {
                if (i != 0)
                    return false;
            }
            return true;
        }
        

        【讨论】:

          【解决方案9】:

          首先你应该检查数组的长度是否相同。

          如果是,那么我们需要对数组进行排序。

          然后遍历两个数组并比较每个元素。

              char[] myArray = new char[] { 'a', 'b', 'c', 'c' };
              char[] urArray = new char[] { 'a', 'b', 'c', 'a' };
          
          
              if (myArray.Length.Equals(urArray.Length))
              {
                  ///
                  /// sort arrays
                  ///
          
                  System.Array.Sort(myArray);
                  System.Array.Sort(urArray);
          
                  for (int i = 0; i < myArray.Length; i++)
                  {
                      if (myArray[i] != urArray[i])
                      {
                          ///
                          /// Arrays do not have same elements.
                          ///
                          break;
          
                      }
          
                  }
                  ///
                  /// if reach this code path the two arrays are equal.
                  ///
          
          
              } else
              {
                  ///
                  /// Arrays not equal lenght
                  ///
          
              }
          

          【讨论】:

            猜你喜欢
            • 2013-10-12
            • 1970-01-01
            • 2016-08-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-27
            • 1970-01-01
            相关资源
            最近更新 更多