且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何交换散列中的键和值

更新时间:2022-04-04 22:28:25

Ruby 有一个用于 Hash 的辅助方法,可以让您将 Hash 视为反转(实质上是通过值访问键):

Ruby has a helper method for Hash that lets you treat a Hash as if it was inverted (in essence, by letting you access keys through values):

{a: 1, b: 2, c: 3}.key(1)
=> :a

如果你想保留倒置哈希,那么 Hash#invert 应该适用于大多数情况:

If you want to keep the inverted hash, then Hash#invert should work for most situations:

{a: 1, b: 2, c: 3}.invert
=> {1=>:a, 2=>:b, 3=>:c}

但是...

如果您有重复的值,invert 将丢弃除最后一次出现的值之外的所有值(因为它会在迭代期间不断替换该键的新值).同样,key 只会返回第一个匹配项:

If you have duplicate values, invert will discard all but the last occurrence of your values (because it will keep replacing new value for that key during iteration). Likewise, key will only return the first match:

{a: 1, b: 2, c: 2}.key(2)
=> :b

{a: 1, b: 2, c: 2}.invert
=> {1=>:a, 2=>:c}

因此,如果您的值是唯一的,您可以使用 Hash#invert.如果没有,那么您可以将所有值保存为数组,如下所示:

So, if your values are unique you can use Hash#invert. If not, then you can keep all the values as an array, like this:

class Hash
  # like invert but not lossy
  # {"one"=>1,"two"=>2, "1"=>1, "2"=>2}.inverse => {1=>["one", "1"], 2=>["two", "2"]} 
  def safe_invert
    each_with_object({}) do |(key,value),out| 
      out[value] ||= []
      out[value] << key
    end
  end
end

注意:此带有测试的代码现在 在 GitHub 上.

Note: This code with tests is now on GitHub.

或者:

class Hash
  def safe_invert
    self.each_with_object({}){|(k,v),o|(o[v]||=[])<<k}
  end
end