简体   繁体   中英

How to merge array of hashes based on key value from deep nested array of hashes

I have an array like this

@info = [
  {"id"=>22014, "act"=>[{"data"=>["show", "video", "audio"], "stud_id"=>11318}]},
  {"id"=>22014, "act"=>[{"data"=>["play", "pause", "start"], "stud_id"=>11439}]},
  {"id"=>22025, "data"=>[{"data"=>["music"], "stud_id"=>11451}]},
  {"id"=>22078, "data"=>[{"data"=>["radio"], "stud_id"=>11705}]},
  {"id"=>22050, "act"=>[{"data"=>["switchon", "switchoff", "flatmusic"], "stud_id"=>11099}]}
]

and I want an array like this from the above array

@info = [
  {"id"=>22014, "act"=>[{"data"=>["show", "video", "audio"], "stud_id"=>11318}, {"data"=>["play", "pause", "start"], "stud_id"=>11439}]},
  {"id"=>22025, "data"=>[{"data"=>["music"], "stud_id"=>11451}]},
  {"id"=>22078, "data"=>[{"data"=>["radio"], "stud_id"=>11705}]},
  {"id"=>22050, "act"=>[{"data"=>["switchon", "switchoff", "flatmusic"], "stud_id"=>11099}]}
]

How can I merge this based on common id values?

info = [
  {"id"=>22014, "act"=>[{"data"=>["show", "video", "audio"], "stud_id"=>11318}]},
  {"id"=>22014, "act"=>[{"data"=>["play", "pause", "start"], "stud_id"=>11439}]},
  {"id"=>22025, "act"=>[{"data"=>["music"], "stud_id"=>11451}]},
  {"id"=>22078, "act"=>[{"data"=>["radio"], "stud_id"=>11705}]},
  {"id"=>22050, "act"=>[{"data"=>["switchon", "switchoff", "flatmusic"], "stud_id"=>11099}]}
]

def combine(info)
  info.group_by {|g|g["id"]}.values.map {|a| {"id" => a.first["id"], "act"=>a.map {|g| g["act"]}}} 
end 

combine info

output

 [{"id"=>22014, "act"=>[[{"data"=>["show", "video", "audio"], "stud_id"=>11318}], [{"data"=>["play", "pause", "start"], "stud_id"=>11439}]]},
 {"id"=>22025, "act"=>[[{"data"=>["music"], "stud_id"=>11451}]]},
 {"id"=>22078, "act"=>[[{"data"=>["radio"], "stud_id"=>11705}]]},
 {"id"=>22050, "act"=>[[{"data"=>["switchon", "switchoff", "flatmusic"], "stud_id"=>11099}]]}]

It's quite basic Ruby. I leave up to you the case where not ids_act && h_act .

info = [
  {"id"=>22014, "act"=>[{"data"=>["show", "video", "audio"], "stud_id"=>11318}]},
  {"id"=>22014, "act"=>[{"data"=>["play", "pause", "start"], "stud_id"=>11439}]},
  {"id"=>22025, "data"=>[{"data"=>["music"], "stud_id"=>11451}]},
  {"id"=>22078, "data"=>[{"data"=>["radio"], "stud_id"=>11705}]},
  {"id"=>22050, "act"=>[{"data"=>["switchon", "switchoff", "flatmusic"], "stud_id"=>11099}]}
]

ids = {}

info.each do | h |
    puts "h=#{h}"
    h_id     = h["id"]
    id_found = ids[h_id] # nil or previously encountered id
    puts "id_found=#{id_found.inspect}"

    if id_found
    then # concatenate act content
        h_act   = h["act"]
        ids_act = id_found["act"]
        ids_act = ids_act.concat(h_act) if ids_act && h_act
    else # store the current hash
        ids[h_id] = h
    end
end

new_info = ids.collect{ | k, v | v }
puts '--- new_info ---'
puts new_info

Execution :

$ ruby -w t.rb 
h={"id"=>22014, "act"=>[{"data"=>["show", "video", "audio"], "stud_id"=>11318}]}
id_found=nil
h={"id"=>22014, "act"=>[{"data"=>["play", "pause", "start"], "stud_id"=>11439}]}
id_found={"id"=>22014, "act"=>[{"data"=>["show", "video", "audio"], "stud_id"=>11318}]}
h={"id"=>22025, "data"=>[{"data"=>["music"], "stud_id"=>11451}]}
id_found=nil
h={"id"=>22078, "data"=>[{"data"=>["radio"], "stud_id"=>11705}]}
id_found=nil
h={"id"=>22050, "act"=>[{"data"=>["switchon", "switchoff", "flatmusic"], "stud_id"=>11099}]}
id_found=nil
--- new_info ---
{"id"=>22014, "act"=>[{"data"=>["show", "video", "audio"], "stud_id"=>11318}, {"data"=>["play", "pause", "start"], "stud_id"=>11439}]}
{"id"=>22025, "data"=>[{"data"=>["music"], "stud_id"=>11451}]}
{"id"=>22078, "data"=>[{"data"=>["radio"], "stud_id"=>11705}]}
{"id"=>22050, "act"=>[{"data"=>["switchon", "switchoff", "flatmusic"], "stud_id"=>11099}]}

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