2014-10-13 2 views
1

У меня есть две строковые массивы, newArray и oldArray, и я хочу использовать Enumberable.Except, чтобы удалить все элементы, которые находятся в newArray, которые также находятся в oldArray, а затем записать результат в файл csv.Enumerable.Except with IEqualityComparer

Однако мне нужно использовать пользовательский сопоставитель для проверки сходства форматирования (если в одном массиве есть новый символ строки, а не другой, я не хочу, чтобы этот элемент записывался в файл).

Мой код как сейчас:

 string newString = File.ReadAllText(csvOutputFile1); 
     string[] newArray = newString.Split(new string[] {sentinel}, StringSplitOptions.RemoveEmptyEntries); 
     string oldString = File.ReadAllText(csvOutputFile2); 
     string[] oldArray = oldString.Split(new string[] { sentinel }, StringSplitOptions.None); 

     IEnumerable<string> differnceQuery = newArray.Except(oldArray, new Comparer()); 

     using (var wtr = new StreamWriter(diffFile)) 
     { 
      foreach (var s in differnceQuery) 
      { 
       wtr.WriteLine(s.Trim() + "#!#"); 
      } 
     } 

и пользовательский класс Comparer:

class Comparer : IEqualityComparer<string> 
{ 
    public bool Equals(string x, string y) 
    { 
     x = x.ToString().Replace(" ", "").Replace("\n", "").Replace("\r", ""); 
     y = y.ToString().Replace(" ", "").Replace("\n", "").Replace("\r", ""); 
     if (x == y) 
      return true; 
     else 
      return false; 
    } 
    public int GetHashCode(string row) 
    { 
     int hCode = row.GetHashCode(); 
     return hCode; 
    } 
} 

Результирующий файл не опуская разница форматирования элементов между двумя массивами. Поэтому, хотя он ловит элементы, которые находятся в newArray, но не в oldArray (как и должно быть), он также помещает элементы, которые отличаются друг от друга только из-за \ n или что-то, даже если в моем пользовательском сопоставлении я их удаляю.

То, что я действительно не понимаю, - это когда я отлаживаю и просматриваю свой код, я вижу, что каждая пара элементов анализируется в моем классе сопоставления, но только когда они равны. Если, например, строка «This is \ nthe 1st term» находится в newArray, а строка «This is the first array» находится в oldArray, отладчик даже не вводит класс сравнения, а вместо этого перескакивает прямо в часть строки моей кода в основном классе.

+1

не ваше выполнение 'GetHashCode' нужно вернуть одинаковые значения хэша для строк, которые отличаются только форматированием? – davisoa

+0

Просто для справки, это было очень полезно. http://stackoverflow.com/questions/4095395/whats-the-role-of-gethashcode-in-the-iequalitycomparert-in-net?rq=1 –

ответ

3

просто: ваш хеш-код неправильно отражает ваш метод равенства. Строки, такие как "a b c" и "abc", возвращают разные значения от GetHashCode, поэтому никогда не будет обойти до тестирования Equals. GetHashCodeдолжен вернуть тот же результат для любых двух значений, которые могут быть равны. Однако нет необходимости в том, чтобы две строки, которые не, равны обратному разные хеш-коды (хотя это очень желательно, в противном случае все войдет в одно и то же хэш-ведро).

Я предполагаю вы могли бы использовать:

// warning: probably not very efficient 
return x.Replace(" ", "").Replace("\n", "").Replace("\r", "").GetHashCode(); 

но это выглядит довольно дорогие (большой потенциал для мусора строк, которые будут созданы все время)

+0

Спасибо Marc. Это сработало, но вы правы, не очень эффективны. Это нужно сделать сейчас, спасибо! –

Смежные вопросы