快速查找重复哈希值的所有键的方法

时间:2013-04-03 19:59:09

标签: ruby hash

我有一个哈希如下:

hash = {"Monday" => "a", "Tuesday" => "b", "Wednesday" => "c", "Thursday" => "b", "Friday" => "c"}

我想获得一个新的哈希:

{"a" => "Monday", "b" => "Tuesday, Thursday" , "c" => "Wednesday, Friday"}

Hash#invert只给出第一个值并丢失重复值。有效的方法吗?

4 个答案:

答案 0 :(得分:3)

hash.inject({}){ |h, (k,v)| (h[v] ||= []) << k; h }
=> {"a"=>["Monday"], "b"=>["Tuesday", "Thursday"], "c"=>["Wednesday", "Friday"]}

答案 1 :(得分:2)

result = hash.inject({}){|m, kv| m[kv.last] ||= []; m[kv.last] << kv.first; m}

这将为您提供以下形式的哈希:

{"a" => ["Monday"], "b" => ["Tuesday", "Thursday"] , "c" => ["Wednesday", "Friday"] }

如果您绝对需要它们作为逗号分隔列表,您可以在以后加入它们:

result = Hash(*result.map{|k, v| [k, v.join(', ')]})

或者在第一次迭代时附加它们:

result = hash.inject({}) do |m, kv| 
  if m[kv.last]
    m[kv.last] << ", " 
  else
    m[kv.last] = ""
  end
  m[kv.last] << kv.first
  m
end

答案 2 :(得分:0)

使用来自Facets的几个抽象的功能方法:

require 'facets'
hash.map_by { |k, v| [v, k] }.mash { |k, vs| [k, vs.join(", ")] }
#=> {"a"=>["Monday"], "b"=>["Tuesday", "Thursday"], "c"=>["Wednesday", "Friday"]} 

答案 3 :(得分:0)

each_with_object是一种替代方法,不确定我是否可以某种方式摆脱三元组。 。

 hash.each_with_object({}) { |kv,new_hash| k,v = kv; new_hash[v] = new_hash[v] ? new_hash[v] + ',' + k : k}
 => {"a"=>"Monday", "b"=>"Tuesday,Thursday", "c"=>"Wednesday,Friday"}