Ruby 请教 hash 比较方法

zlx_star · 2012年11月22日 · 最后由 zlx_star 回复于 2012年11月23日 · 3078 次阅读

请教如何判定以下 hash 相同。

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

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

#1 楼 @zgm #2 楼 @fresh_fish 不好意思,我没表达清楚。我希望 {'a' => 1, 'b' => 2} == {'a' => '1', 'b' => '2'} #==> true

已修改原题

Hash[h1.map{ |k, v| [k.to_s, v.to_s]}] == h2

#4 楼 @fresh_fish 第二种情况通不过

@zlx_star

这个问题比较麻烦... 你要写一个递归的比较方法:

def compare a, b
  case a
  when Hash
    return false unless b.is_a?(Hash) and b.size == a.size
    a.sort.zip b.sort do |(ka, va), (kb, vb)|
      return false unless compare(ka, kb) and compare(va, vb)
    end
    true
  when Array
    ... # 类似 Hash
  else
    return false if b.is_a?(Hash) or b.is_a?(Array)
    a.to_s == b.to_s
  end
end

当然上面的代码还是有一点点问题,就是引用到父元素时会无限循环 (例如: h = {}; h['a'] = h), 所以还得把比较过的元素存起来验证是否已经比较过了...

def split_hash(h)
  g = {}
  h.each_pair do |k, v|
    g[k.to_s] = v.is_a?(Hash) ? split_hash(v) : v.to_s
  end
  g
end

split_hash(h1) == h2

这个版本 仅仅满足你题目的需求

1.9.3-p286 :004 > a = {'a' => 1, 'b' => 2 }
 => {"a"=>1, "b"=>2} 
1.9.3-p286 :005 > b = {'a' => 1, 'b' => 2 }
 => {"a"=>1, "b"=>2} 
1.9.3-p286 :006 > a == b
 => true 

@luikore @fresh_fish 没必要那么麻烦,通过字符串比较就可以了

a = {'a' => 1, 'b' => 2}.to_s.gsub(/"/im,'')
b = {'a' => '1', 'b' => '2'}.to_s.gsub(/"/im,'')
a == b # true

字符串比较有顺序问题

#9 楼 @jonny

Good! 👍

简单点,可以写作:

a = {'a' => 1, 'b' => 2}.to_s.gsub("\"", "")
b = {'a' => '1', 'b' => '2'}.to_s.gsub("\"", "")
p a == b

#9 楼 @jonny

a = {'a' => '""1""'}.to_s.gsub(/"/im,'')
b = {'a' => '\\1\\'}.to_s.gsub(/"/im,'')
a == b # true

:(

需要 登录 后方可回复, 如果你还没有账号请 注册新账号