Hash invert in Ruby?

后端 未结 8 1784
星月不相逢
星月不相逢 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 01:12

    Lots of other good answers. Just wanted to toss this one in too for Ruby 2.0 and 1.9.3:

    hash = {apple: [1, 14], orange: [7, 12, 8, 13]}
    
    Hash[hash.flat_map{ |k, v| v.map{ |i| [i, k] } }]
    # => {1=>:apple, 14=>:apple, 7=>:orange, 12=>:orange, 8=>:orange, 13=>:orange}
    

    This is leveraging: Hash::[] and Enumerable#flat_map

    Also in these new versions there is Enumerable::each_with_object which is very similar to Enumerable::inject/Enumerable::reduce:

    hash.each_with_object(Hash.new){ |(k, v), inverse|
      v.each{ |e| inverse[e] = k }
    }
    

    Performing a quick benchmark (Ruby 2.0.0p0; 2012 Macbook Air) using an original hash with 100 keys, each with 100 distinct values:

    Hash::[] w/ Enumerable#flat_map
                155.7 (±9.0%) i/s -        780 in   5.066286s
    Enumerable#each_with_object w/ Enumerable#each
                199.7 (±21.0%) i/s -        940 in   5.068926s
    

    Shows that the each_with_object variant is faster for that data set.

    0 讨论(0)
  • 2021-01-13 01:14

    One way to achieve what you're looking for:

    arr = [{["k1"] => ["a", "b", "c"]}, {["k2"] => ["d", "e", "f"]}]
    
    results_arr = []
    arr.each do |hsh|
      hsh.values.flatten.each do |val|
        results_arr << { [val] => hsh.keys.first }···
      end
    end
    
    
    Result: [{["a"]=>["k1"]}, {["b"]=>["k1"]}, {["c"]=>["k1"]}, {["d"]=>["k2"]}, {["e"]=>["k2"]}, {["f"]=>["k2"]}]
    
    0 讨论(0)
提交回复
热议问题