如何反转哈希,维护重复键

时间:2014-03-23 23:58:02

标签: ruby

从最初的哈希t

t = {"1"=>1, "2"=>2, "3"=>2, "6"=>3, "5"=>4, "4"=>1, "8"=>2, "9"=>2, "0"=>1, "7"=>1}

我需要按如下方式交换键和值:

t = {"1"=>1, "2"=>2, "3"=>2, "6"=>3, "5"=>4, "1"=>4, "8"=>2, "9"=>2, "1"=>0, "1"=>7}

保持哈希的结构(即,不折叠重复键)。

然后我将从这个哈希中创建一个数组。

有办法做到这一点吗?我试过这个:

t.find_all{ |key,value| value == 1 }   # pluck all elements with values of 1
#=> [["1", 1], ["4", 1], ["0", 1], ["7", 1]]

但是它返回一个新数组,初始哈希值没有改变。

以下情况也不起作用:

t.invert.find_all{ |key,value| value == 1 }  
#=> []

1 个答案:

答案 0 :(得分:3)

这是一种方法:

>> t = {"1" => 1, "2" => 2, "3" => 2, "6" => 3, "5" => 4, "4" => 1, "8" => 2, "9" => 2, "0" => 1, "7" => 1}

Hash#compare_by_identity允许按值重复但按对象ID唯一的键:

>> h = Hash.new.compare_by_identity
>> t.each_pair{ |k,v| h[v.to_s] = v.to_i }

t的反向哈希:

>> h
#=> {"1" => 1, "2" => 2, "2" => 3, "3" => 6, "4" => 5, "1" => 4, "2" => 8, "2" => 9, "1" => 0, "1" => 7} 

然后,您可以使用find_all检索元素数组,而不会改变h

>> h.find_all{ |k,_|  k == "1" }
#=> [["1", 1], ["1", 1], ["1", 1], ["1", 1]]

keep_if返回变异的h

>> h.keep_if{ |k,_|  k == "1"  }        
#=> {"1"=>1, "1"=>1, "1"=>1, "1"=>1}
>> h
#=> {"1"=>1, "1"=>1, "1"=>1, "1"=>1}

请注意,此解决方案假定您希望在哈希中维护字符串键和整数值的模式。如果您需要整数键,compare_by_identity对您没有帮助。