1

我有一个哈希如下:

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

我想得到一个新的哈希,它将是:

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

Hash#invert只给出第一个值并丢失重复的值。有什么有效的方法来做到这一点?

4

4 回答 4

3
hash.inject({}){ |h, (k,v)| (h[v] ||= []) << k; h }
=> {"a"=>["Monday"], "b"=>["Tuesday", "Thursday"], "c"=>["Wednesday", "Friday"]}
于 2013-04-03T20:23:47.470 回答
1
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
于 2013-04-03T20:02:02.117 回答
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"]} 
于 2013-04-03T20:03:54.667 回答
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"}
于 2013-04-03T20:11:23.973 回答