1

I have a array of hashes like this.

[
 {"package_details"=>{"name"=>"Package3", "price"=>3000.0, "id"=>"281"},"event_id"=>336},
 {"package_details"=>{"name"=>"2000/-", "price"=>2000.0, "id"=>"280"}, "event_id"=>337}, 
 {"package_details"=>{"name"=>"Package1", "price"=>1000.0, "id"=>"282"},"event_id"=>337},
 {"package_details"=>{"name"=>"Package2", "price"=>2000.0, "id"=>"283"},"event_id"=>337}
]

And I want this be like this.

[
  {"event_id"=>336, "package_details"=>[
    {"name"=>"Package3", "price"=>3000.0, "id"=>"281"}
  ]},
  {"event_id"=>337, "package_details"=>[
    {"name"=>"2000/-", "price"=>2000.0, "id"=>"280"},
    {"name"=>"Package1", "price"=>1000.0, "id"=>"282"},
    {"name"=>"Package2", "price"=>2000.0, "id"=>"283"}
  ]},
]

Hash should merge according to the equal event_id values and there event can have many packages.

I want to know the easiest way to do this. Though I was able to do with many if and else s.

3
  • You have wrong outer hash syntax. Maybe do you need to change outer hash to array? Commented Mar 24, 2013 at 8:53
  • -1 There is no data structure that is like what you say that you have, nor is it possible to create what you want. You are using only { which denotes a Hash literal, but it appears that you have combinations of arrays and hashes. Please edit your question to show the actual data you have. (Hint: p my_data will print the .inspect result.) Commented Mar 24, 2013 at 15:55
  • I have edited your question with the data structure I believe you actually have (an array of hashes) and changed your desired structure to one that makes sense (an array of hashes where one of the keys in each references an array of hashes). Commented Mar 24, 2013 at 16:16

2 Answers 2

5

The simplest transformation that gives you the functional result you want is to use Enumerable#group_by.

details = [
 {"package_details"=>{"name"=>"Package3","price"=>3000.0,"id"=>"281"},"event_id"=>336},
 {"package_details"=>{"name"=>"2000/-","price"=>2000.0,"id"=>"280"},"event_id"=>337}, 
 {"package_details"=>{"name"=>"Package1","price"=>1000.0,"id"=>"282"},"event_id"=>337},
 {"package_details"=>{"name"=>"Package2","price"=>2000.0,"id"=>"283"},"event_id"=>337}
]

grouped = details.group_by{ |d| d["event_id"] }
#=> {
#=>   336=>[
#=>     {"package_details"=>{"name"=>"Package3", "price"=>3000.0, "id"=>"281"}, "event_id"=>336}],
#=>   337=>[
#=>     {"package_details"=>{"name"=>"2000/-", "price"=>2000.0, "id"=>"280"}, "event_id"=>337},
#=>     {"package_details"=>{"name"=>"Package1", "price"=>1000.0, "id"=>"282"}, "event_id"=>337},
#=>     {"package_details"=>{"name"=>"Package2", "price"=>2000.0, "id"=>"283"}, "event_id"=>337}]
#=> }

With this you can just do:

grouped.each do |event_id, packages|
  # event_id is the actual value, like 336
  # packages is an array of hashes from your original
end

If you really need exactly the format you described, then you can do this:

transformed = details.group_by{ |d| d["event_id"] }.map do |event_id, hashes|
  {
    "event_id"=>event_id,
    "package_details"=>hashes.map{ |h| h["package_details"] }
  }
end    
#=> [
#=>   {"event_id"=>336, "package_details"=>[
#=>     {"name"=>"Package3", "price"=>3000.0, "id"=>"281"}
#=>   ]},
#=>   {"event_id"=>337, "package_details"=>[
#=>     {"name"=>"2000/-", "price"=>2000.0, "id"=>"280"},
#=>     {"name"=>"Package1", "price"=>1000.0, "id"=>"282"},
#=>     {"name"=>"Package2", "price"=>2000.0, "id"=>"283"}
#=>   ]}
#=> ]

The above runs through the groupings and transforms ("maps") each key/value pair to a custom hash, the contents of which have been munged according to your desires.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Phorogz. Though i have committed the code now, I ll change to this method when i am re-factoring. thanks again.
0

Finally I got it. For above input hash, I was manage to get a like this.

[{"packages"=>[{"name"=>"Package3", "price"=>3000.0, "id"=>"281"}], "event_id"=>336}, {"packages"=>[{"name"=>"2000/-", "price"=>2000.0, "id"=>"280"}, {"name"=>"Package1", "price"=>1000.0, "id"=>"282"}, {"name"=>"Package2", "price"=>2000.0, "id"=>"283"}], "event_id"=>337}

With using these methods. This is not the most accurate way. But it has done the the trick for me.

event_id_array = Array.new
events_with_packages = Array.new
events.each.each do |event|
event_id_array.push(event.id)
end
event_id_array.uniq!.each_with_index do |e_id, i|
  events_with_packages[i]  = Hash.new
  events_with_packages[i]["event_id"] = e_id
  events_with_packages[i]["packages"] = Array.new
    events.each do |event|
    tmp_event = Hash.new
    if(event.id==e_id)
      tmp_event["id"] = event[:ep_id]
      tmp_event["price"] = event[:price]
      tmp_event["name"] = event[:ep_name]
      events_with_packages[i]["packages"].push(tmp_event)
    end
  end
end
events_with_packages # the answer

1 Comment

This is not the right way to do it. Phorogz have showed how to do it. But i ll keep this, if anybody is interested.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.