Sunday, May 1, 2011

What is the best way to remap a Hash in Ruby?

Is there a simple way of remapping a hash in ruby the following way:


{:name => "foo", :value => "bar"}


{"foo" => "bar"}

Preferably in a way that makes it simple to do this operation while iterating over an array of this type of hashes:


[{:name => "foo", :value => "bar"}, {:name => "foo2", :value => "bar2"}]


{"foo" => "bar", "foo2" => "bar2"}


From stackoverflow
  • arr = [ {:name=>"foo", :value=>"bar"}, {:name=>"foo2", :value=>"bar2"}]
    result = {}
    arr.each{|x| result[x[:name]] = x[:value]}
    # result is now {"foo2"=>"bar2", "foo"=>"bar"}
    morbaq : Yes, this is almost what I did also, but I used x.values[0] and x.values[1] instead of x[:name] and x[:value], in case I don't know the keys in advance. I was fishing for an even simpler way to do this, but there might not be one...
    Vanson Samuel : Hash values are out of order so you can't do x.values[0] and x.values[1]
    Gishu : +1 to Vanson.. you can see that the result contents are already out of order since its a Hash.
    morbaq : Yes, I didn't think of that. +1 for pointing that out.
  • A modified version of Vanson Samuel's code does the intended. It's a one-liner, but quite a long one.

    arr = [{:name=>"foo", :value=>"bar"}, {:name=>"foo2", :value=>"bar2"}]
    arr.inject({}){|r,item| r.merge({item['name'] => item['value']})}
    # result {"foo" => "bar", "foo2" => "bar2"}

    I wouldn't say that it's prettier than Gishu's version, though.

  • As a general rule of thumb, if you have a hash of the form {:name => "foo", :value => "bar"}, you're usually better off with using a tuple of ["foo", "bar"].

    arr = [["foo", "bar"], ["foo2", "bar2"]]
    arr.inject({}) { |accu, (key, value)| accu[key] = value; accu }


Post a Comment