Hash invert in Ruby?

后端 未结 8 1789
星月不相逢
星月不相逢 2021-01-13 00:27

I\'ve got a hash of the format:

{key1 => [a, b, c], key2 => [d, e, f]}

and I want to end up with:

{ a => key1, b =         


        
8条回答
  •  无人共我
    2021-01-13 00:56

    If you want to correctly deal with duplicate values, then you should use the Hash#inverse from Facets of Ruby

    Hash#inverse preserves duplicate values, e.g. it ensures that hash.inverse.inverse == hash

    either:

    • use Hash#inverse from here: http://www.unixgods.org/Ruby/invert_hash.html

    • use Hash#inverse from FacetsOfRuby library 'facets'

    usage like this:

    require 'facets'
    
    h = {:key1 => [:a, :b, :c], :key2 => [:d, :e, :f]}
     => {:key1=>[:a, :b, :c], :key2=>[:d, :e, :f]} 
    
    h.inverse
     => {:a=>:key1, :b=>:key1, :c=>:key1, :d=>:key2, :e=>:key2, :f=>:key2} 
    

    The code looks like this:

    # this doesn't looks quite as elegant as the other solutions here,
    # but if you call inverse twice, it will preserve the elements of the original hash
    
    # true inversion of Ruby Hash / preserves all elements in original hash
    # e.g. hash.inverse.inverse ~ h
    
    class Hash
    
      def inverse
        i = Hash.new
        self.each_pair{ |k,v|
          if (v.class == Array)
            v.each{ |x|
              i[x] = i.has_key?(x) ? [k,i[x]].flatten : k
            }
          else
            i[v] = i.has_key?(v) ? [k,i[v]].flatten : k
          end
        }
        return i
      end
    
    end
    
    
    h = {:key1 => [:a, :b, :c], :key2 => [:d, :e, :f]}
     => {:key1=>[:a, :b, :c], :key2=>[:d, :e, :f]} 
    
    h.inverse
     => {:a=>:key1, :b=>:key1, :c=>:key1, :d=>:key2, :e=>:key2, :f=>:key2} 
    

提交回复
热议问题