Comment comparer deux dictionnaires en C #

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 existe 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 comporte de nombreuses 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.Je suis en train d’utiliser. 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. C’est formidable 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:

  • Itérer sur les paires clé / valeur dans dict2
  • Pour chaque entrée, recherchez la valeur dans dict1 et filtrez toutes les entrées dont les deux valeurs sont identiques.
  • Créez un dictionnaire à partir des entrées restantes (c’est-à-dire celles où la valeur 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 – il serait peut- être correct 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 rejoindre 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(); 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, la manière la 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’object en dictionnaire puis, après les avoir soustraits du concept défini, les éléments de résultat doivent être vides s’ils sont identiques.

  public static IDictionary ToDictionary(this object source) { var fields = source.GetType().GetFields( BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance).ToDictionary ( propInfo => propInfo.Name, propInfo => propInfo.GetValue(source) ?? ssortingng.Empty ); var properties = source.GetType().GetProperties( BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance).ToDictionary ( propInfo => propInfo.Name, propInfo => propInfo.GetValue(source, null) ?? ssortingng.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.ToSsortingng().Equals(secondDic[pair.Key].ToSsortingng()) ); } public static bool IsAnonymousType(this object instance) { if (instance == null) return false; return instance.GetType().Namespace == null; } public static IDictionary ToFlattenDictionary(this object source, ssortingng parentPropertyKey = null, IDictionary parentPropertyValue = null) { var propsDic = parentPropertyValue ?? new Dictionary(); foreach (var item in source.ToDictionary()) { var key = ssortingng.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 du code