简体   繁体   中英

Hash modification issue in hash, replacing value in ruby

I would like to get rid of the value: <value> key value inside each of the attributes in the hash. And make it like this: "total_interactions": 493.667 Below is the incorrect format followed by the expected good format I hope to achieve in json.

{
    "3": {
        "total_interactions": {
            "value": 493.667
        },
        "shares": {
            "value": 334
        },
        "comments": {
            "value": 0
        },
        "likes": {
            "value": 159.66666666666666
        },
        "total_documents": 6
    },
    "4": {
        "total_interactions": {
            "value": 701
        },
        "shares": {
            "value": 300
        },
        "comments": {
            "value": 0
        },
        "likes": {
            "value": 401
        },
        "total_documents": 1
    }
}

I want it to be like this:

{
    "3": {
        "total_interactions": 493.6666666666667,
        "shares": 334,
        "comments": 0,
        "likes": 159.66666666666666,
        "total_documents": 6
    },
    "4": {
        "total_interactions": 701,
        "shares": 300,
        "comments": 0,
        "likes": 401,
        "total_documents": 1
    }
}

Here is the code that is supposed to do this but is not working. Nothing affected. Not sure what is wrong

# the result_hash variable is the first hash with value: <value>
result_hash.each do |hash_item|
            hash_item.each do |key,value_hash|
                if( !value_hash.nil? )
                    value_hash.each do |k,v|
                        hash_item[key] = v
                    end
                end             
            end
        end

Max Williams' code is perfect for in-place. You can also do this in functional style to get a new, corrected hash:

hash.merge(hash) {|k,v| v.merge(v) {|kk,vv| vv.is_a?(Hash) && vv['value'] ? vv['value'] : vv }}
hash = {"3"=>{"total_documents"=>6, "comments"=>{"value"=>0}, "total_interactions"=>{"value"=>493.667}, "shares"=>{"value"=>334}, "likes"=>{"value"=>159.666666666667}}, 
        "4"=>{"total_documents"=>1, "comments"=>{"value"=>0}, "total_interactions"=>{"value"=>701}, "shares"=>{"value"=>300}, "likes"=>{"value"=>401}}}

hash.each do |k,v| 
  v.each do |k2, v2|
    if v2.is_a?(Hash) && v2["value"]
      hash[k][k2] = v2["value"]
    end
  end
end

after this:

hash = {"3"=>{"total_documents"=>6, "comments"=>0, "total_interactions"=>493.667, "shares"=>334, "likes"=>159.666666666667}, 
        "4"=>{"total_documents"=>1, "comments"=>0, "total_interactions"=>701, "shares"=>300, "likes"=>401}}

If you do not wish to mutate your initial hash, h ,you can do this:

h.each_with_object({}) { |(k,v),g|
  g[k] = v.each_with_object({}) { |(kk,vv),f|
    f[kk] = (Hash === vv) ? vv[:value] : vv } }
  #=> {:"3"=>{:total_interactions=>493.667,
  #           :shares=>334,
  #           :comments=>0,
  #           :likes=>159.66666666666666,
  #           :total_documents=>6},
  #   :"4"=>{:total_interactions=>701,
  #           :shares=>300,
  #           :comments=>0,
  #           :likes=>401,
  #           :total_documents=>1}} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM