私は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
誰でも私にこれを行うための最良のアルゴリズムを教えてもらえますか?私はアルゴリズムを書きましたが、ループがたくさんあります。短くて効率的なアイデアを探しています。また、LINQクエリ式またはLINQラムダ式を使用したソリューションも必要です。 C#で.Net Framework 3.5を使用しています。 Except()メソッドについて何かを見つけました。しかし残念ながら、その方法で何が起こっているのか理解できませんでした。提案されたアルゴリズムを説明する人がいるとすばらしい。
キーが同じであることをすでに確認している場合は、次を使用できます。
var dict3 = dict2.Where(entry => dict1[entry.Key] != entry.Value)
.ToDictionary(entry => entry.Key, entry => entry.Value);
説明すると、これは:
dict2
のキー/値ペアを反復処理しますdict1
の値を検索し、2つの値が同じであるエントリを除外しますdict1
に現れるように各ペアからキーと値を取得することにより、残りのエントリ(つまり、dict2
値が異なるエントリ)から辞書を作成します。KeyValuePair<TKey, TValue>
-itmightの等式に依存することを回避することに注意してください。個人的に私はこれをより明確にします。 (辞書キーにカスタム等値比較子を使用している場合にも機能しますが、ToDictionary
にも渡す必要があります。)
試してください:
dictionary1.OrderBy(kvp => kvp.Key)
.SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key))
違いを確認するには、
dic1.Count == dic2.Count && !dic1.Except(dic2).Any();
次のコードは、すべての異なる値を返します
dic1.Except(dic2)
あなたは両方の辞書が同じキーを持っていると述べたので、この仮定が正しければ、あなたは何も派手なものを必要としません:
foreach (var key in d1.Keys)
{
if (!d1[key].Equals(d2[key]))
{
d3.Add(key, d2[key]);
}
}
それとも私はあなたの問題を誤解していますか?
それらをキーで結合し、両方の値を選択できるはずです。次に、値が同じか異なるかに基づいてフィルタリングできます。最後に、キーと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 );
}
}
}
両方の辞書に同じキーがあると仮定すると、最も簡単な方法は
_var result = a.Except(b).ToDictionary(x => x.Key, x => x.Value);
_
[〜#〜] edit [〜#〜]
a.Except(b)
はb.Except(a)
とは異なる結果を与えることに注意してください。
_a.Except(b): Price 20
b.Except(a): Price 40
_
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);
オブジェクトをディクショナリに変換してから、セットコンセプトに従ってそれらを減算すると、結果アイテムは同一である場合に空になります。
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.