Group JSON by data?
arrays, json, ruby, ruby-on-rails
Solution
The magic you want is `Enumerable#group_by`:
require 'json'
all = JSON.parse(DATA.read)['events']['event']
all.group_by{ |h| [h['city'],h['state'],h['country']] }.each do |loc,events|
puts "'#{loc.join(',')}': #{events.length} event#{:s if events.length!=1}"
print "--> "
puts events.map{ |e| e['status'] }.join(', ')
end
#=> 'Birmingham,AL,US': 3 events
#=> --> Delivered, Out For Delivery, Arrival Scan
#=> 'Doraville,GA,US': 2 events
#=> --> Departure Scan, Arrival Scan
#=> 'Spartanburg,SC,US': 2 events
#=> --> Departure Scan, Arrival Scan
#=> 'Greensboro,NC,US': 2 events
#=> --> Departure Scan, Origin Scan
#=> ',,US': 1 event
#=> --> Billing Information Received
Note that, in the above, `loc` is the three-element array returned from the block evaluated by `group_by`, and `events` is an array of all items in the same group.
Problem
I've got the following JSON data: ``` { "events": { "event": [ { "city":"Birmingham", "state":"AL", "country":"US", "lat":"33.5206608", "lng":"-86.80249", "status":"Delivered", "occured_at":"2012-04-06 14:17:00 UTC" }, { "city":"Birmingham", "state":"AL", "country":"US", "lat":"33.5206608", "lng":"-86.80249", "status":"Out For Delivery", "occured_at":"2012-04-06 04:44:00 UTC" }, { "city":"Birmingham", "state":"AL", "country":"US", "lat":"33.5206608", "lng":"-86.80249", "status":"Arrival Scan", "occured_at":"2012-04-05 19:07:00 UTC" }, { "city":"Doraville", "state":"GA", "country":"US", "lat":"33.8981579", "lng":"-84.2832564", "status":"Departure Scan", "occured_at":"2012-04-05 17:08:00 UTC" }, { "city":"Doraville", "state":"GA", "country":"US", "lat":"33.8981579", "lng":"-84.2832564", "status":"Arrival Scan", "occured_at":"2012-04-05 11:15:00 UTC" }, { "city":"Spartanburg", "state":"SC", "country":"US", "lat":"34.9495672", "lng":"-81.9320482", "status":"Departure Scan", "occured_at":"2012-04-05 08:42:00 UTC" }, { "city":"Spartanburg", "state":"SC", "country":"US", "lat":"34.9495672", "lng":"-81.9320482", "status":"Arrival Scan", "occured_at":"2012-04-05 08:21:00 UTC" }, { "city":"Greensboro", "state":"NC", "country":"US", "lat":"36.0726354", "lng":"-79.7919754", "status":"Departure Scan", "occured_at":"2012-04-05 04:45:00 UTC" }, { "city":"Greensboro", "state":"NC", "country":"US", "lat":"36.0726354", "lng":"-79.7919754", "status":"Origin Scan", "occured_at":"2012-04-05 00:11:00 UTC" }, { "city":null, "state":null, "country":"US", "status":"Billing Information Received", "occured_at":"2012-04-04 18:20:27 UTC" } ] } } ``` What I need to do is group the data by a combination of city, state and country, but still return the data from each item. So for instance, group by "Birmingham, AL, US" but still be able to iterate through the `status`'s of each event (ie. Delivered, Out for Delivery, Arrival Scan) with that.