J'ai deux dictionnaires génériques.Les deux ont les mêmes clés.Mais les valeurs peuvent être différentes.Je veux comparer le deuxième dictionnaire avec le 1er dictionnaire.S'il y a des différences entre les valeurs, je veux stocker ces valeurs dans un dictionnaire séparé.
1st Dictionary
------------
key Value
Barcode 1234566666
Price 20.00
2nd Dictionary
--------------
key Value
Barcode 1234566666
Price 40.00
3rd Dictionary
--------------
key Value
Price 40
Quelqu'un peut-il me donner un meilleur algorithme pour le faire? J'ai écrit un algorithme, mais il a beaucoup de boucles.Je cherche une idée courte et efficace.Également comme une solution utilisant une expression de requête LINQ ou une expression LINQ lamda.J'utilise. Net Framework 3.5 avec C #. J'ai trouvé quelque chose à propos de la méthode Except () .Mais, malheureusement, je ne comprenais pas ce qui se passait avec cette méthode.Il est génial si quelqu'un explique l'algorithme suggéré.J'aime toujours apprendre :).
Merci Thabo.
Si vous avez déjà vérifié que les clés sont les mêmes, vous pouvez simplement utiliser:
var dict3 = dict2.Where(entry => dict1[entry.Key] != entry.Value)
.ToDictionary(entry => entry.Key, entry => entry.Value);
Pour expliquer, cela va:
dict2
dict1
et filtrez les entrées dont les deux valeurs sont identiques.dict1
est différente) en prenant la clé et la valeur de chaque paire telles qu'elles apparaissent dans dict2
.Notez que cela évite de s’appuyer sur l’égalité de KeyValuePair<TKey, TValue>
- il [pourrait peut-être convenir de s'en fier, mais personnellement, je trouve cela plus clair. (Cela fonctionnera également lorsque vous utiliserez un comparateur d'égalité personnalisé pour les clés de dictionnaire - bien que vous deviez également le transmettre à ToDictionary
.)
essayez:
dictionary1.OrderBy(kvp => kvp.Key)
.SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key))
Vous avez mentionné que les deux dictionnaires ont les mêmes clés. Par conséquent, si cette hypothèse est correcte, vous n'avez besoin de rien d'extraordinaire:
foreach (var key in d1.Keys)
{
if (!d1[key].Equals(d2[key]))
{
d3.Add(key, d2[key]);
}
}
Ou est-ce que je comprends mal votre problème?
pour vérifier toute différence,
dic1.Count == dic2.Count && !dic1.Except(dic2).Any();
le code suivant renvoie toutes les valeurs différentes
dic1.Except(dic2)
Vous devriez pouvoir les joindre sur leurs clés et sélectionner les deux valeurs. Ensuite, vous pouvez filtrer selon que les valeurs sont identiques ou différentes. Enfin, vous pouvez convertir la collection en dictionnaire avec les clés et les deuxièmes valeurs.
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 );
Utiliser une boucle ne devrait pas être trop mal non plus. Je soupçonne qu'ils auraient des caractéristiques de performance similaires.
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 );
}
}
}
En supposant que les deux dictionnaires aient les mêmes clés, le moyen le plus simple est de
var result = a.Except(b).ToDictionary(x => x.Key, x => x.Value);
MODIFIER
Notez que a.Except(b)
donne un résultat différent de 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);
Edit: Si vous êtes sûr que toutes les clés sont identiques, vous pouvez faire:
var diff = d2.Where(x=>x.Value != d1[x.Key]).ToDictionary(x=>x.Key, x=>x.Value);
convertir l'objet en dictionnaire puis, après les avoir soustraits, les éléments de résultat doivent être vides s'ils sont identiques.
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.