134 votes

Comment comparer deux hachages ?

J'essaie de comparer deux hachages Ruby à l'aide du code suivant :

#!/usr/bin/env ruby

require "yaml"
require "active_support"

file1 = YAML::load(File.open('./en_20110207.yml'))
file2 = YAML::load(File.open('./locales/en.yml'))

arr = []

file1.select { |k,v|
  file2.select { |k2, v2|
    arr << "#{v2}" if "#{v}" != "#{v2}"
  }
}

puts arr

La sortie sur l'écran est le fichier complet du fichier 2. Je sais pertinemment que les fichiers sont différents, mais le script ne semble pas le remarquer.

0 votes

Duplicata possible de Comparaison des hachages en rubis

196voto

the Tin Man Points 69148

Vous pouvez comparer directement les hachages pour vérifier l'égalité :

hash1 = {'a' => 1, 'b' => 2}
hash2 = {'a' => 1, 'b' => 2}
hash3 = {'a' => 1, 'b' => 2, 'c' => 3}

hash1 == hash2 # => true
hash1 == hash3 # => false

hash1.to_a == hash2.to_a # => true
hash1.to_a == hash3.to_a # => false


Vous pouvez convertir les hachages en tableaux, puis obtenir leur différence :

hash3.to_a - hash1.to_a # => [["c", 3]]

if (hash3.size > hash1.size)
  difference = hash3.to_a - hash1.to_a
else
  difference = hash1.to_a - hash3.to_a
end
Hash[*difference.flatten] # => {"c"=>3}

Simplifier encore :

Attribution de la différence via une structure ternaire :

  difference = (hash3.size > hash1.size) \
                ? hash3.to_a - hash1.to_a \
                : hash1.to_a - hash3.to_a
=> [["c", 3]]
  Hash[*difference.flatten] 
=> {"c"=>3}

Faire tout cela en une seule opération et se débarrasser de la difference variable :

  Hash[*(
  (hash3.size > hash1.size)    \
      ? hash3.to_a - hash1.to_a \
      : hash1.to_a - hash3.to_a
  ).flatten] 
=> {"c"=>3}

4 votes

Y a-t-il un moyen d'obtenir les différences entre les deux ?

5 votes

Les hachages peuvent avoir la même taille, mais contenir des valeurs différentes. Dans ce cas, les deux hash1.to_a - hash3.to_a y hash3.to_a - hash1.to_a peut retourner des valeurs non vides bien que hash1.size == hash3.size . La partie après EDIT n'est valable que si les hachages sont de taille différente.

3 votes

Sympa, mais j'aurais dû arrêter pendant qu'il était encore temps. A.size > B.size ne signifie pas nécessairement que A inclut B. Il faut toujours prendre l'union des différences symétriques.

40voto

liu fengyun Points 81

Vous pouvez essayer le hashdiff qui permet une comparaison profonde des hachages et des tableaux dans le hachage.

Voici un exemple :

a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
b = {a:{y:3}, b:{y:3, z:30}}

diff = HashDiff.diff(a, b)
diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]

4 votes

J'avais des hachages assez profonds qui provoquaient l'échec des tests. En remplaçant le got_hash.should eql expected_hash con HashDiff.diff(got_hash, expected_hash).should eql [] J'obtiens maintenant une sortie qui montre exactement ce dont j'ai besoin. C'est parfait !

0 votes

Wow, HashDiff est génial. J'ai pu rapidement essayer de voir ce qui a changé dans un énorme tableau JSON imbriqué. Merci !

0 votes

Votre bijou est génial ! Super utile pour écrire des spécifications impliquant des manipulations JSON. Merci.

22voto

Guilherme Bernal Points 5789

Si vous voulez savoir quelle est la différence entre deux hachages, vous pouvez faire ceci :

h1 = {:a => 20, :b => 10, :c => 44}
h2 = {:a => 2, :b => 10, :c => "44"}
result = {}
h1.each {|k, v| result[k] = h2[k] if h2[k] != v }
p result #=> {:a => 2, :c => "44"}

11voto

Evan Points 1850

Rails est dépréciation de le site diff método.

Pour un petit mot rapide :

hash1.to_s == hash2.to_s

0 votes

J'oublie toujours ça. Il y a beaucoup de contrôles d'égalité qui sont rendus faciles en utilisant to_s .

24 votes

Il échouera si des hachages égaux ont des clés dans un ordre différent : {a:1, b:2} == {b:2, a:1} => vrai, {a:1, b:2}.to_s == {b:2, a:1}.to_s => faux

2 votes

Ce qui est une fonctionnalité ! :D

0voto

Wolfram Arnold Points 3490

Cette question a été traitée dans " Comparaison des hachages en rubis ". Rails ajoute un diff méthode à des hachages. Cela fonctionne bien.

7 votes

Méthode de diffusion est déprécié à partir des versions de Rails plus récentes que la v4.0.2.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X