在Ruby中反转哈希

时间:2012-06-03 22:17:58

标签: ruby hashmap

如何反转哈希中的元素,保持相同的值和键,但是在哈希中反转它们的顺序。

像这样:

{ "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }

并将其转换为:

{ "1" => "spider", "lala" => "54", "10" => "cool", "4" => "happiness" }

或者,也许我可以向后运行each循环,从哈希中的最后一个元素开始,而不是第一个?

9 个答案:

答案 0 :(得分:62)

您可以将哈希转换为数组,反过来,然后将其转换回哈希:

reversed_h = Hash[h.to_a.reverse]

Hash#to_a为您提供了一个数组数组,内部数组是简单的[key,value]对,然后使用Array#reverse反转该数组,Hash[]转换{{1}成对回哈希。

Ruby 2.1添加了Array#to_h方法,现在您可以说:

[key,value]

答案 1 :(得分:6)

在Ruby 2.1+中,您可以合并reverse_eachto_h

{foo: 1, bar: 2}.reverse_each.to_h
#=> {:bar=>2, :foo=>1}

答案 2 :(得分:4)

hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
reversed_hash = Hash[hash.to_a.reverse]

答案 3 :(得分:4)

h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
p Hash[h.reverse_each.map{|e| e}]
#=> {"1"=>"spider", "lala"=>"54", "10"=>"cool", "4"=>"happiness"}

但这会留下一种不好的味道(就像其他答案一样,这就像这个一样正常)。如果你必须这样做,那可能表明哈希不是最好的选择。

答案 4 :(得分:2)

reversed_h = Hash[h.to_a.collect(&:reverse)]

答案 5 :(得分:1)

在纯红宝石中,您可以通过hash.map(&:reverse).to_hhash.reverse_each.to_h

在Rails中,您可以通过hash.invert

答案 6 :(得分:0)

或者,您可以使用reducemerge将项目添加到新哈希的前面:

hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
hash.reduce({}){ |memo, object| Hash[*object].merge(memo) }

但是,这太疯狂了:D

答案 7 :(得分:0)

Ruby 1.8.7中,记录哈希中元素的顺序不在我们的控制之下,因此上述方法都不起作用。在Ruby 1.9.3中,事情起作用并以其他答案所依赖的方式记录。

$ irb1.8
h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
Hash[h.to_a().reverse()]
=> {"lala"=>"54", "1"=>"spider", "10"=>"cool", "4"=>"happiness"}
quit
$ irb1.9.1
h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
Hash[h.to_a().reverse()]
=>{"1"=>"spider", "lala"=>"54", "10"=>"cool", "4"=>"happiness"}

Ruby 1.8.7的方式对我来说根深蒂固,以至于我误解了这个问题很长一段时间。我认为它要求Hash#invert的方法:即转换哈希,使范围映射到域。该方法丢弃重复项。 LuísRamalho提供的a method没有,但它有点笨拙。这有点短:

$ irb
def invertWithDuplicates(original)
  inverse = Hash.new() { |hash, key| hash[key] = []; }
  original.each_pair() { |key, value| inverse[value].push(key); }
  return inverse
end
h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "cool" }
invertWithDuplicates(h)
=> {"happiness"=>["4"], "cool"=>["1", "10"], "54"=>["lala"]}

很抱歉偏离了OP的主题,尽管我认为这确实符合帖子的标题“在Ruby中反转哈希”。

答案 8 :(得分:0)

如果需要:

hash = {:a => :x, :b => :y, :c => :y, :d => :z}

收件人:

{:x => [:a], :y => [:b, c], :z => [:d] }

可以:

h={};hash.to_a.each{|e|h[e[1]]||=[];h[e[1]]<<e[0]};h