简体   繁体   English

比较两个数组是否相同的最快方法是什么?

[英]What's the fastest way to compare two arrays for equality?

I have two arrays of objects which are likely to have the same values, but in a different order, eg 我有两个对象数组,它们可能具有相同的值,但顺序不同,例如

{ "cat", "dog", "mouse", "pangolin" }

{ "dog", "pangolin", "cat", "mouse" }

I wish to treat these two arrays as equal. 我希望将这两个数组视为相等。 What's the fastest way to test this? 测试这个的最快方法是什么?

I can't guarantee that this is the fastest , but it's certainly quite efficient: 我不能保证这是最快的 ,但它肯定非常有效:

bool areEquivalent = array1.Length == array2.Length 
                     && new HashSet<string>(array1).SetEquals(array2);

EDIT: SaeedAlg and Sandris raise valid points about different frequencies of duplicates causing problems with this approach. 编辑:SaeedAlg和Sandris提出了有关重复的不同频率的有效点,从而导致这种方法出现问题。 I can see two workarounds if this is important (haven't given much thought to their respective efficiencies): 如果这很重要,我可以看到两个解决方法(没有充分考虑它们各自的效率):

1.Sort the arrays and then compare them sequentially. 1.排序数组然后按顺序进行比较。 This approach, in theory, should have quadratic complexity in the worst case. 理论上,这种方法在最坏的情况下应该具有二次复杂性。 Eg: 例如:

return array1.Length == array2.Length
       && array1.OrderBy(s => s).SequenceEqual(array2.OrderBy(s => s));

2.Build up a frequency-table of strings in each array and then compare them. 2.在每个数组中建立一个字符串频率表,然后进行比较。 Eg: 例如:

if(array1.Length != array2.Length)
   return false;

var f1 = array1.GroupBy(s => s)
               .Select(group => new {group.Key, Count = group.Count() });

var f2 = array2.GroupBy(s => s)
               .Select(group => new {group.Key, Count = group.Count() });

return !f1.Except(f2).Any();

I think the only reasonable way is to sort them and then compare. 我认为唯一合理的方法是对它们进行排序然后进行比较。

Sorting requires O(n logn) and comparing O(n) , so that's still a total of O(n logn) 排序需要O(n logn)并比较O(n) ,因此仍然是O(n logn)的总和

Have you tried something like 你尝试过类似的东西吗?

string[] arr1 = {"cat", "dog", "mouse", "pangolin"};

string[] arr2 = {"dog", "pangolin", "cat", "mouse"};

bool equal = arr1.Except(arr2).Count() == 0 && arr2.Except(arr1).Count() == 0;

将两个数组转换为HashSet并使用setequals

I would use a HashSet, assuming there are no duplicates 假设没有重复项,我会使用HashSet

string[] arr1 = new string[] { "cat", "dog", "mouse", "pangolin" };
string[] arr2 = new string[] { "dog", "pangolin", "cat", "mouse" };

bool result = true;
if (arr1.Length != arr2.Length)
{
    result = false;
}
else
{
    HashSet<string> hash1 = new HashSet<string>(arr1);
    foreach (var s in arr2)
    {
        if (!hash1.Contains(s))
            result = false;
    }
}

Edit: 编辑:
If you just have four elements it might be faster to skip the HashSet and use arr1.Contains in the comparison. 如果你只有四个元素,跳过HashSet并在比较中使用arr1.Contains可能会更快。 Measure and pick the fastest for your array size. 测量并选择最快的阵列大小。

Pseudocode : 伪代码:

A:array
B:array
C:hashtable

if A.length != B.length then return false;

foreach objA in A
{
H = objA;
if H is not found in C.Keys then
C.add(H as key,1 as initial value);
else
C.Val[H as key]++;
}

foreach objB in B
{
H = objB;
if H is not found in C.Keys then
return false;
else
C.Val[H as key]--;
}

if(C contains non-zero value)
return false;
else
return true;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM