Tony DiNitto
Tony DiNitto

Reputation: 1239

Inverting a hash: Making multiple hash keys from an array

I'm trying to get a hash that has an array of values inverted such that the keys are now values. From an expression like this:

StackOverflow.transform({ 1 => ['A', 'E'] , 2 => ["B"]})

I'm trying to get this result:

{"A"=>1, "E"=>1, "B"=>2}

I have this:

class StackOverflow
  def self.transform(old)
    a = Hash[old.map { |k,v| v.product([k]) }.first]
  end
end

but the keys are all separated as individual keys (not grouped). It returns:

{"A"=>1, "E"=>1}

I'm also trying to downcase the keys, but I feel like after I figure out this inversion issue properly, I'll be able to (hopefully?) figure out the downcasing logic as well.

Upvotes: 0

Views: 114

Answers (2)

Mark Thomas
Mark Thomas

Reputation: 37517

You were very close. You want to use flat_map instead of first.

class StackOverflow
  def self.transform(old)
    Hash[old.flat_map { |k,v| v.product([k]) }]
  end
end

You were using first to flatten the array.

Upvotes: 4

Cary Swoveland
Cary Swoveland

Reputation: 110685

Another way:

class StackOverflow
  def self.transform(old)
    val = nil
    old.each_with_object(Hash.new { |h,k| h[k]=val }) do |(k,v),h|
      val = k
      h.values_at(*v)
    end
  end
end

old = { 1=>['A', 'E'], 2=>['B'] }
StackOverflow.transform(old)
  #=> {"A"=>1, "E"=>1, "B"=>2} 

Upvotes: 0

Related Questions