将哈希值(即数组)反转为新的单个键

Inverting a hash value (that's an array) into new individual keys

我有以下内容:

lumpy_hash = { 1 => ["A", "B"] }

然后如果我在这个散列上调用 Hash#invert,我想得到:

lumpy_hash = {"A" => 1, "B" => 1}

我没有通过使用 Hash#invert 得到它。这样做有什么想法吗?我不确定我是否应该尝试 Hash#mapHash#invert.

有很多方法可以做到这一点。这是一个:

Hash[lumpy_hash.map { |k,v| v.product([k]) }.first]
 #=> {"A"=>1, "B"=>1} 

我认为 Hash#invert 方法在这里没有用。

步骤:

enum = lumpy_hash.map
  #=> #<Enumerator: {1=>["A", "B"]}:map> 
k,v = enum.next
  #=> [1, ["A", "B"]] 
k #=> 1 
v #=> ["A", "B"] 
a = v.product([k])
  #=> ["A", "B"].product([1])
  #=> [["A", 1], ["B", 1]] 
Hash[a]
  #=> {"A"=>1, "B"=>1}

这是另一种使用散列 default value 的方法。这个比较有意思:

key,value = lumpy_hash.to_a.first
  #=> [1, ["A","B"]]
Hash.new { |h,k| h[k]=key }.tap { |h| h.values_at(*value) }
  #=> {"A"=>1,"B"=>1}

Object#tap 将空散列传递给它的块,并将其分配给块变量 h。添加三个键值对后的块 returns h,每个键值对的值等于散列的默认值。它仅通过计算哈希没有的键的值来添加对!

这是另一个更简单的方法:

lumpy_hash.flat_map{|k,vs| vs.map{|v| {v => k}}}.reduce(&:merge)
 => {"A"=>1, "B"=>1}