在Ruby中反转哈希

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

像这样:

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

并将其转换为:

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

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

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

 reversed_h = Hash[h.to_a.reverse] 

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

Ruby 2.1添加了一个Array#to_h方法,所以你现在可以说:

 reversed_h = h.to_a.reverse.to_h 

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

 {foo: 1, bar: 2}.reverse_each.to_h #=> {:bar=>2, :foo=>1} 
 hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" } reversed_hash = Hash[hash.to_a.reverse] 
 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"} 

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

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

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

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

但是,这很疯狂:D

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

 $ irb1.8
 h = {“4”=>“幸福”,“10”=>“酷”,“lala”=>“54”,“1”=>“蜘蛛”}
散列[h.to_a()。反向()]
 => {“lala”=>“54”,“1”=>“蜘蛛”,“10”=>“酷”,“4”=>“幸福”}
放弃
 $ irb1.9.1
 h = {“4”=>“幸福”,“10”=>“酷”,“lala”=>“54”,“1”=>“蜘蛛”}
散列[h.to_a()。反向()]
 => {“1”=>“蜘蛛”,“lala”=>“54”,“10”=>“酷”,“4”=>“幸福”}

Ruby 1.8.7的方式对我来说是如此坚定,以至于我在很长一段时间内误解了这个问题。 我认为它要求Hash#invert的方法 :即转换哈希值,使范围映射到域。 该方法丢弃重复项。 路易斯·拉马霍(LuísRamalho)提供的方法没有,但它有点笨重。 这有点短:

 $ irb
 def invertWithDuplicates(original)
   inverse = Hash.new(){| hash,key |  hash [key] = [];  }
   original.each_pair(){| key,value | 逆[值] .push(键);  }
  返回逆
结束
 h = {“4”=>“幸福”,“10”=>“酷”,“lala”=>“54”,“1”=>“酷”}
 invertWithDuplicates(H)
 => {“happiness”=> [“4”],“酷”=> [“1”,“10”],“54”=> [“lala”]}

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

在纯ruby中,你可以通过hash.map(&:reverse).to_hhash.reverse_each.to_h

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