2013-09-27 3 views
1

У меня есть два словаря, и я хочу их сравнить. Я хочу игнорировать случай и возвращать только false, если они имеют разные значения. Вот мой код.Как сравнить значения словаря, игнорирующие случай

var dic1 = new Dictionary<String, String>(StringComparer.CurrentCultureIgnoreCase); 
      dic1.Add("Key 2", "Value 2"); 
      dic1.Add("Key 1", "Value 1"); 


      var dic2 = new Dictionary<String, String>(StringComparer.CurrentCultureIgnoreCase); 
      dic2.Add("Key 1", "Value 1"); 
      dic2.Add("Key 2", "Value 2"); 

      var areEqual = dic1.OrderBy(r => r.Key).SequenceEqual(dic2.OrderBy(r => r.Key)); 

      Console.WriteLine(areEqual); 

Как вы можете видеть, я использую метод SequenceEqual класса словаря для сравнения двух словарей. Я заказал их с помощью ключа, чтобы результат не был ложным, если позиция ключа отличается. Проблема, которую я не могу понять, состоит в том, как игнорировать случай в ключе и значениях и возвращать false, только если значения различны. В моем случае значение 1 и VALUE 1 равны, и результат должен быть правдой. Это не мое дело.

ответ

2

Сортировать по ключу, выберите значение и использовать перегрузку SequenceEqual с StringComparer.OrdinalIgnoreCase:

bool areEqual = dic1.OrderBy(x => x.Key).Select(kv => kv.Value) 
    .SequenceEqual(dic2.OrderBy(x => x.Key).Select(kv => kv.Value), StringComparer.OrdinalIgnoreCase); 

Это исполнение в виде последовательности байт в байт сравнения, аналогичный strcmp, который не только позволяет избежать ошибок из лингвистический интерпретация по существу символических строк, но обеспечивает лучшую производительность.

http://msdn.microsoft.com/en-us/library/ms973919.aspx

+0

Спасибо Тим Я использовал свой собственный пользовательский компаньон, но, как ваше решение, лучше, так что он ответил как ответ. Благодаря! –

+0

@AfrazAli: _ «Я заказал их по ключу, чтобы результат не был ложным, если позиция ключа различна». _ Нужно ли вам принимать ключ или нет? Вы можете напрямую использовать 'dic1.Values', чтобы сравнивать только значения. Поэтому, возможно, лучше использовать 'dic1.Values.OrderBy (v => v) .SequenceEqual (dic2.Values ​​...' –

+0

Да, Тим, я хочу также скомпоновать ключи. Ваше решение отлично работает в соответствии с моими требованиями. Спасибо! –

0

Во-первых, проверьте длины - если они не равны, то верните false.

Далее перебирайте каждый элемент и сравнивайте значения (при условии, что они имеют одинаковый порядок). Вы также можете сделать это, перебирая первый словарь и проверив, есть ли каждый элемент во втором словаре. Как только это не так, выйдите из цикла или верните false.

+0

Я хочу игнорировать вручную сравнение словарей и хочу использовать перегрузку методы SequenceEqual на данный момент. –

2

Вы должны действительно проверить, равны ли длины, и если два словаря имеют одинаковые ключи. После того как вы пройдете мимо этой части, вы можете использовать следующий фрагмент:

var dic1 = new Dictionary<String, String>(); 
dic1.Add("Key 2", "Value 2"); 
dic1.Add("Key 1", "Value 1"); 

var dic2 = new Dictionary<String, String>(); 
dic2.Add("Key 1", "Value 1"); 
dic2.Add("Key 2", "Value 2"); 

bool areEqual = dic1.OrderBy(x => x.Key).Select(x => x.Value.ToUpperInvariant()) 
    .SequenceEqual(dic2.OrderBy(x => x.Key).Select(x => x.Value.ToUpperInvariant())); 

Console.WriteLine(areEqual); 
+0

Это не сработает. См. Http://stackoverflow.com/questions/3550213/in-c-sharp-what-is-the-difference-between-toupper-and-toupperinvariant – dzendras

+0

@dzendras Он будет работать, только не в отдельных случаях, как Турция. Спасибо за предложение, я отредактировал и заменил «ToUpper» на «ToUpperInveriant». –

+0

В любом случае ToUpper - это далеко не путь. Каждый ToUpper создает новый экземпляр строки. Представьте, что происходит, когда словарь содержит 10 миллионов элементов. Вы должны использовать перегрузку с помощью сравнения (как указано в других ответах). Твоя ошибка. – dzendras

1

Закончен с использованием пользовательского сопоставления для сравнения значений. Вот код.

class Program 
    { 
     static void Main(string[] args) 
     { 
      var dic1 = new Dictionary<String, String>(); 
      dic1.Add("Key 2", "Value 2"); 
      dic1.Add("Key 1", "Value 1"); 


      var dic2 = new Dictionary<String, String>(); 
      dic2.Add("Key 1", "Value 1"); 
      dic2.Add("Key 2", "Value 2"); 

      var areEqual = dic1.OrderBy(r => r.Key).SequenceEqual(dic2.OrderBy(r => r.Key), new ProductComparer()); 

      Console.WriteLine(areEqual); 

      Console.ReadLine(); 
     } 
    } 



    internal class ProductComparer : IEqualityComparer<KeyValuePair<string, string>> 
    { 
     public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y) 
     { 
      Boolean areEqual = (String.Compare(x.Key, y.Key, StringComparison.OrdinalIgnoreCase) == 0) && (String.Compare(x.Value, y.Value, StringComparison.OrdinalIgnoreCase) == 0); 
      return areEqual; 
     } 

     public int GetHashCode(KeyValuePair<string, string> obj) 
     { 
      return obj.GetHashCode(); 
     } 
    } 
+0

Не нужно, вам просто нужно использовать уже доступный 'StringComparer'. –

+0

Я пробовал это, но не мог понять, как использовать его в моем сценарии. Можете ли вы отправить образец кода с помощью StringComparer? –

+0

Спасибо, Тим, принял ваш ответ! –

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