Ruby中的哈希反转?

Ruby中的哈希反转?,ruby,arrays,hash,Ruby,Arrays,Hash,我得到了格式的散列: {key1 => [a, b, c], key2 => [d, e, f]} 最后我想说: { a => key1, b => key1, c => key1, d => key2 ... } 实现这一点最简单的方法是什么 我正在使用Ruby on Rails 更新 好的,我设法从服务器日志中提取了真实的对象,它是通过AJAX推送的 Parameters: {"status"=>{"1"=>["1", "14"], "

我得到了格式的散列:

{key1 => [a, b, c], key2 => [d, e, f]}
最后我想说:

{ a => key1, b => key1, c => key1, d => key2 ... }
实现这一点最简单的方法是什么

我正在使用Ruby on Rails

更新

好的,我设法从服务器日志中提取了真实的对象,它是通过AJAX推送的

  Parameters: {"status"=>{"1"=>["1", "14"], "2"=>["7", "12", "8", "13"]}}

如果要反转这样的哈希格式,以下内容可能会对您有所帮助:

a = {:key1 => ["a", "b", "c"], :key2 => ["d", "e", "f"]}
a.inject({}) do |memo, (key, values)|
  values.each {|value| memo[value] = key }
  memo
end
这将返回:

{"a"=>:key1, "b"=>:key1, "c"=>:key1, "d"=>:key2, "e"=>:key2, "f"=>:key2}
这给

new_hash # {"a"=>"key1", "b"=>"key1", "c"=>"key1", "d"=>"key2", "e"=>"key2", "f"=>"key2"}

好吧,让我们猜猜看。你说你有一个数组,但我同意Benoit的说法,你可能有一个散列。功能性方法:

 h = {:key1 => ["a", "b", "c"], :key2 => ["d", "e", "f"]}
 h.map { |k, vs| Hash[vs.map { |v| [v, k] }] }.inject(:merge)
 #=> {"a"=>:key1, "b"=>:key1, "c"=>:key1, "d"=>:key2, "e"=>:key2, "f"=>:key2}
此外:

第一变体

hash.map{|k, v| v.map{|f| {f => k}}}.flatten
#=> [{"a"=>:key1}, {"b"=>:key1}, {"c"=>:key1}, {"d"=>:key2}, {"e"=>:key2}, {"f"=>:key2}] 

UPD

好的,您的哈希是:

hash = {"status"=>{"1"=>["1", "14"], "2"=>["7", "12", "8", "13"]}}
hash["status"].inject({}){|h, (k,v)| v.map{|f| h[f] = k}; h}
#=> {"12"=>"2", "7"=>"2", "13"=>"2", "8"=>"2", "14"=>"1", "1"=>"1"}

实现您所追求目标的一种方法:

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"]}]
arr=[{[“k1”]=>[“a”、“b”、“c”]},{[“k2”]=>[“d”、“e”、“f”]}]
结果_arr=[]
arr.每个do | hsh|
hsh.values.flatte.each do|val|
结果_arrhsh.keys.first}···
结束
结束
结果:[{[“a”]=>[“k1”]}、{[“b”]=>[“k1”]}、{[“c”]=>[“k1”]}、{[“d”]=>[“k2”]}、{[“e”]=>[“k2”]}、{[“f”]=>[“k2”]}]

如果要正确处理重复值,则应使用哈希#逆 从红宝石的各个方面来看

哈希#逆
保留重复值
, e、 g.它确保
hash.inverse.inverse==hash

要么:

  • 从这里使用哈希#逆:

  • 使用FaceSofRuby库“facets”中的哈希#逆

用法如下:

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} 
# 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} 
代码如下所示:

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} 
# 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} 

在一个值对应多个键的情况下,如本例中的“c”

{ :key1 => ["a", "b", "c"], :key2 => ["c", "d", "e"]}
…其他一些答案不会给出预期结果。我们需要反向散列将密钥存储在数组中,如下所示:

{ "a" => [:key1], "b" => [:key1], "c" => [:key1, :key2], "d" => [:key2], "e" => [:key2] }
这应该可以做到:

reverse = {}
hash.each{ |k,vs|
    vs.each{ |v|
        reverse[v] ||= []
        reverse[v] << k
    }
}
reverse={}
hash.each{k,vs|
vs.each{v|
反向[v]| |=[]

反向[v]还有很多其他的好答案。我只想在Ruby 2.0和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}
这就是杠杆作用:以及

在这些新版本中,还有一个非常类似于/:

使用包含100个键的原始散列(每个键有100个不同的值)执行快速(Ruby 2.0.0p0;2012 Macbook Air):

Hash::[]带可枚举平面映射
155.7(±9.0%)i/s-780 in 5.066286s
可枚举#每个#带有_对象w/可枚举#每个
199.7(±21.0%)i/s-940英寸5.068926秒

显示
每个带有_object的
变量对于该数据集的速度更快。

我不知道如何让它打印出一个数组,以便我可以读取它以进行实验。不过,你尝试了什么?
p array
打印出内容。你确定它是一个数组而不是散列吗?你描述它的方式不明确。为什么要使用奇怪的伪数组-代码?显示为Ruby对象…更简单的是——使用Hash#FacetsOfRuby的逆函数——需要“facets”这看起来不错,但不能很好地工作;我现在更新了帖子以显示实际对象。正如我们在前面的问题中讨论的,fl00r,在不需要时使用inject不是一个好的选择。此外,您使用的是map bu是的,我知道,我是一个功能性的偏执者:-)我一直得到“
散列的奇数个参数”
Hash[vs.]
应该是
Hash[*vs.map{v,k]}。flatte]
注入(:merge)
仅为1.9。无论如何,这证明我应该切换到1.9:-)@undur\u gongor,你是否使用Yes(1.8.6)。我一直在混淆这一点。我现在如何修复错误的评论?@undur\u gongor:不要担心旧的评论,人们可以看到整个对话。你可以删除它们,但我似乎是在单独说话:-)
reverse = {}
hash.each{ |k,vs|
    vs.each{ |v|
        reverse[v] ||= []
        reverse[v] << k
    }
}
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}
hash.each_with_object(Hash.new){ |(k, v), inverse|
  v.each{ |e| inverse[e] = k }
}