Newy
Newy

Reputation: 40137

How to move attributes in Ruby hash "up" one level

x = {:name => "John", :data => {:physical => {:age => 25, :weight => 150}}}

I'm looking to move the subattributes of data up one level (but not necessarily simply flatten all attributes). In this case, I essentially want to move the :physical attribute "up" one level.

I'm trying this

y = x[:data']
y.each{ |key| x[key] = y[key] }

but I get ...

x = x.except(:data)
 => {:name=>"John", [:physical, {:age=>25, :weight=>150}]=>nil} 

I'm looking for ...

 => {:name=>"John", :physical => {:age=>25, :weight=>150}} 

Upvotes: 8

Views: 2071

Answers (3)

gordie
gordie

Reputation: 1955

Based on @micha%c3%abl-witrant's answer and because I needed this on a nested array, here's function doing it recursively :

def levelUpAttribute(attr,myHash,parent = nil)

  if myHash.is_a?(Hash)
    #level up matching keys
    myHash = myHash.merge(myHash.delete(attr) || {})
    #recursion
    myHash.each do |key, value|
      myHash[key] = levelUpAttribute(attr,value,key)
    end
  end

  myHash

end

x = levelUpAttribute(:data,x)

Upvotes: 0

the Tin Man
the Tin Man

Reputation: 160571

I'd go after it this way:

x = {:name => "John", :data => {:physical => {:age => 25, :weight => 150}}}

x[:physical] = x.delete(:data)[:physical]

pp x #=> {:name=>"John", :physical=>{:age=>25, :weight=>150}}

Upvotes: 2

Michaël Witrant
Michaël Witrant

Reputation: 7714

Try this:

x = x.merge(x.delete(:data))

Upvotes: 9

Related Questions