2010-11-11 3 views
12

У меня есть два массива объектов, которые, вероятно, имеют одинаковые значения, но в другом порядке, например.Какой самый быстрый способ сравнить два массива для равенства?

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

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

Я хочу рассматривать эти два массива как равные. Какой самый быстрый способ проверить это?

ответ

18

Я не могу гарантировать, что это быстрый, но это, конечно, весьма эффективно:

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

EDIT: SaeedAlg и Sandris поднять действительные пункты о различных частотах дублей, вызывающих проблемы с этим подходом. Я вижу два обходных решения, если это важно (не придали большого значения их соответствующей эффективности):

1. Содержите массивы, а затем последовательно сравните их. Такой подход теоретически должен иметь квадратичную сложность в худшем случае. т.д .:

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

2.Build вверх частотную таблицу строк в каждом массиве, а затем сравнить их. Например:

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(); 
+0

Br illiant, thanks :) – izb

+0

Это как @Albin Sunnanbo ответ может быть, вы вернетесь, два массива равны, и они не равны. –

+0

@SaeedAlg: Можете ли вы привести пример? – Ani

0

Я хотел бы использовать 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:
Если вы только четыре элемента может быть быстрее, чтобы пропустить HashSet и использовать arr1 . Сопоставляет в сравнении. Измерьте и выберите самый быстрый размер вашего массива.

+0

У этого есть положительная ложная ошибка, хеш не поддерживает, чтобы не сделать уникальное значение для разных предметов. –

+0

это теоретически дешевле, но на практике может быть проще сказать hash1 = HashSet (arr1); hash2 = HashSet (arr2); hash1.SetEquals (hash2) –

4

Я думаю, что единственный разумный способ - сортировать их, а затем сравнивать.

Сортировка требует O(n logn) и сравнения O(n), так что до сих пор в общей сложности O(n logn)

+0

Конечно, это предполагает, что вы можете сравнивать два слова в постоянное время. Если слова могут быть длиннее, хотя они также способствуют времени выполнения. – Frank

+0

Сравнение двух строк легко, поскольку сравнение GetHashCode() –

+1

Сравнение двух хеш-кодов не гарантирует равенства. – devios1

1

Преобразование обоих массивов в HashSets и использовать setequals

2

Вы пробовали что-то вроде

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

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

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

псевдокод:

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; 
Смежные вопросы