1. ホーム
  2. ruby

[解決済み] 2つのハッシュを比較するにはどうすればよいですか?

2022-08-27 17:18:30

質問

以下のコードで2つのRubyのHashを比較しようとしています。

#!/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

画面に出力されるのは、file2からのフルファイルです。ファイルが違うことは事実ですが、スクリプトはそれを拾っていないようです。

どのように解決すればよいのでしょうか?

ハッシュが等しいかどうかを直接比較することができます。

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



ハッシュを配列に変換して、その差分を取得することができます。

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}


さらに簡略化する。

三項構造による差分を割り当てる。

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

一回の操作ですべてを行うこと、そして difference という変数を削除します。

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