2012-03-03 28 views
11

私は2つの汎用辞書を持っています。どちらも同じキーを持っています。しかし、値は異なっています。私は第二辞書と第一辞書を比較したい。別の辞書。Cで2つの辞書を比較する方法

1st Dictionary 
------------ 
key  Value 

Barcode 1234566666 
Price  20.00 


2nd Dictionary 
-------------- 
key  Value 

Barcode 1234566666 
Price  40.00 


3rd Dictionary 
-------------- 
key  Value 

Price  40 

いずれかが私にthis.Iを行うための最善のアルゴリズムを与えることはできますが、アルゴリズムを書いたが、それはloops.Iの多くはLINQのクエリ式やLINQを使用して、ソリューションのような短いと効率的なidea.Alsoを求めています持っています私は.Net Framework 3.5をC#で使用しています。私はExcept()メソッドについていくつかを見つけました。残念ながら、そのメソッドで何が起こっているのか理解できませんでした。

ありがとうございました Thabo。

+0

キーは最初の辞書ではなく、第二、またはその逆に表示されている場合、あなたは何をする何をしたいですか? –

+0

いいえ...実際には、キーは名前とカウントが同じでなければなりません。アルゴリズムに行く前にiscontains()メソッドでチェックしています。事前に感謝しています。 – Thabo

答えて

24

すでにキーが同じであることを確認した場合、あなただけ使用することができます。

var dict3 = dict2.Where(entry => dict1[entry.Key] != entry.Value) 
       .ToDictionary(entry => entry.Key, entry => entry.Value); 

を説明するために、この意志:キー/値のペアでオーバー

  • 反復各エントリについて
  • dict2dict1の値をルックアップし、二つの値が同じdictionar
  • フォームであるすべてのエントリを除外残りのエントリ(すなわち、 dict1の値が異なるもの)は、dict2のように各ペアからキーと値を取得します。 ことに依存していても大丈夫かもしれませんが、個人的に私はこの明確見つける - これはKeyValuePair<TKey, TValue>の平等に頼って回避していること

注意。 (あなたが辞書のキーにカスタム等値比較子を使用しているときにも動作します - 。あなたも、ToDictionaryにそれを渡す必要があると思いますが)

6

あなたは両方の辞書が同じキーを持っているので、この仮定が正しければ、あなたは空想何を必要としないことを述べた:

 foreach (var key in d1.Keys) 
     { 
      if (!d1[key].Equals(d2[key])) 
      { 
       d3.Add(key, d2[key]); 
      } 
     } 

または私はあなたの問題を誤解していますか?

+0

'!d1 [key] .Equals(d2 [key])' –

+0

これは簡単なことです。なぜなら私は常にOrder n操作を避けたいからです。 – Thabo

+1

あなたは '!'あなたが異なる値を必要とするので、等しい値ではありません。 –

2

キーでそれらを結合し、両方の値を選択できる必要があります。次に、値が同じか違うかに基づいてフィルタリングすることができます。最後に、キーと第2の値を使ってコレクションを辞書に変換することができます。

var compared = first.Join(second, f => f.Key, s => s.Key, (f,s) => new { f.Key, FirstValue = f.Value, SecondValue = s.Value }) 
         .Where(j => j.FirstValue != j.SecondValue) 
         .ToDictionary(j => j.Key, j => j.SecondValue); 

ループを使用するとどちらも悪くないはずです。私は、彼らは同様のパフォーマンスの特性を持っていると思う。

var compared = new Dictionary<string,object>(); 
    foreach (var kv in first) 
    { 
     object secondValue; 
     if (second.TryGetValue(kv.Key, out secondValue)) 
     { 
      if (!object.Equals(kv.Value, secondValue)) 
      { 
       compared.Add(kv.Key, secondValue); 
      } 
     } 
    } 
15

てみてください。両方の辞書を想定し

dictionary1.OrderBy(kvp => kvp.Key) 
      .SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key)) 
+1

これは値と比較されますか?これはコレクションまたはブール値を返しますか? – Thabo

+0

私はいくつかの異なるオプションを試してみましたが、Dictionaryキーは文字列であり、これははるかに速いと思われました。 –

2

は同じキーを持つ、最も簡単な方法は、a.Except(b)は異なる結果を与えることを

var result = a.Except(b).ToDictionary(x => x.Key, x => x.Value); 

EDIT

注意ですb.Except(a)

a.Except(b): Price  20 
b.Except(a): Price  40 
+0

両方の辞書でキーの順序が異なる場合はどうすればいいですか? – Thabo

+1

@Thaboはい。しかし、 'a.Except(b)'は 'b.Except(a)'とは異なる結果を与えることに注意してください。 –

2
var diff1 = d1.Except(d2); 
var diff2 = d2.Except(d1); 
return diff1.Concat(diff2); 

編集:あなたは必ずすべてのキーが同じである場合はあなたが行うことができます:

var diff = d2.Where(x=>x.Value != d1[x.Key]).ToDictionary(x=>x.Key, x=>x.Value); 
+0

しかしこれは辞書にはなりませんが、 'IEnumerable >' –

+1

となります。最初は私たちは辞書を持つことはできませんが、もう一つは私の答えを更新します。 –

5

は、任意の違いを確認するために、次のコード

dic1.Count == dic2.Count && !dic1.Except(dic2).Any(); 

が返すすべて異なる値

dic1.Except(dic2) 
+0

あなたはこの少し説明できますか?:) – Thabo

+1

@Thabo:辞書は同じサイズで、最初のものと2番目のものにない要素がない場合、同等です。 2行目は、最初の行にあり、2行目にないすべての要素を直接返します –

0

を辞書にオブジェクトを変換し、その後集合概念以下にそれらを引きますそれらが同じ場合には、結果項目は空でなければならない。

public static IDictionary<string, object> ToDictionary(this object source) 
    { 
     var fields = source.GetType().GetFields(
      BindingFlags.GetField | 
      BindingFlags.Public | 
      BindingFlags.Instance).ToDictionary 
     (
      propInfo => propInfo.Name, 
      propInfo => propInfo.GetValue(source) ?? string.Empty 
     ); 

     var properties = source.GetType().GetProperties(
      BindingFlags.GetField | 
      BindingFlags.GetProperty | 
      BindingFlags.Public | 
      BindingFlags.Instance).ToDictionary 
     (
      propInfo => propInfo.Name, 
      propInfo => propInfo.GetValue(source, null) ?? string.Empty 
     ); 

     return fields.Concat(properties).ToDictionary(key => key.Key, value => value.Value); ; 
    } 
    public static bool EqualsByValue(this object source, object destination) 
    { 
     var firstDic = source.ToFlattenDictionary(); 
     var secondDic = destination.ToFlattenDictionary(); 
     if (firstDic.Count != secondDic.Count) 
      return false; 
     if (firstDic.Keys.Except(secondDic.Keys).Any()) 
      return false; 
     if (secondDic.Keys.Except(firstDic.Keys).Any()) 
      return false; 
     return firstDic.All(pair => 
      pair.Value.ToString().Equals(secondDic[pair.Key].ToString()) 
     ); 
    } 
    public static bool IsAnonymousType(this object instance) 
    { 

     if (instance == null) 
      return false; 

     return instance.GetType().Namespace == null; 
    } 
    public static IDictionary<string, object> ToFlattenDictionary(this object source, string parentPropertyKey = null, IDictionary<string, object> parentPropertyValue = null) 
    { 
     var propsDic = parentPropertyValue ?? new Dictionary<string, object>(); 
     foreach (var item in source.ToDictionary()) 
     { 
      var key = string.IsNullOrEmpty(parentPropertyKey) ? item.Key : $"{parentPropertyKey}.{item.Key}"; 
      if (item.Value.IsAnonymousType()) 
       return item.Value.ToFlattenDictionary(key, propsDic); 
      else 
       propsDic.Add(key, item.Value); 
     } 
     return propsDic; 
    } 
originalObj.EqualsByValue(messageBody); // will compare values. 

source of the code

関連する問題