Tanner Brandt
Tanner Brandt

Reputation: 43

Search a JSON Response with Ruby and Count Occurances

I can't seem to wrap my head around the following problem today. I am parsing a JSON response from an API that helps me plan how many boxes my items will fill up to fulfill a shipment.

I've saved and parsed the JSON response from the API to a variable called API_response in Rails below. Now I specifically need to count each time "id"=>"Bin1" shows up in this response.

I'm thinking that maybe the best way to do this is to do a select for "id"=>"Bin1" and map it to an array each time and then count the number of indexes in the array so that I have a final count for how many boxes I'll use? How would I go about doing this?

API_response = {"response"=>{"id"=>"1538005707_bc789275d7cc93eca86830e41a44f7a9", "bins_packed"=>[{"bin_data"=>{"w"=>12, "h"=>6, "d"=>12, "id"=>"Bin1", "used_space"=>57.8704, "weight"=>80, "used_weight"=>100, "stack_height"=>5, "order_id"=>"unknown"}, "items"=>[{"id"=>12, "w"=>10, "h"=>5, "d"=>10, "wg"=>80}]}, {"bin_data"=>{"w"=>12, "h"=>6, "d"=>12, "id"=>"Bin1", "used_space"=>57.8704, "weight"=>80, "used_weight"=>100, "stack_height"=>5, "order_id"=>"unknown"}, "items"=>[{"id"=>12, "w"=>10, "h"=>5, "d"=>10, "wg"=>80}]}, {"bin_data"=>{"w"=>12, "h"=>6, "d"=>12, "id"=>"Bin1", "used_space"=>57.8704, "weight"=>80, "used_weight"=>100, "stack_height"=>5, "order_id"=>"unknown"}, "items"=>[{"id"=>12, "w"=>10, "h"=>5, "d"=>10, "wg"=>80}]}], "errors"=>[], "status"=>1, "not_packed_items"=>[]}}

UPDATE I think what I'd actually really love to do is, for each occurrence of Bin1, push the weight of the bin into a new array. So I'd like my final result from my response example above to be an array such as Bin1_Array = [80, 80, 80]

Upvotes: 0

Views: 528

Answers (3)

tekuri
tekuri

Reputation: 146

You may try this:

API_response["response"]["bins_packed"].group_by{|x| x["bin_data"]["id"]}["Bin1"].count

Here group_by will group the elements of ["bin_data"]["id"], once we group we can get the the we can easily get the group count of specific key.

Upvotes: 0

Marcin Kołodziej
Marcin Kołodziej

Reputation: 5313

Assuming you just need the number 3 for your example,

API_response["response"]["bins_packed"].count do |item| 
  item["bin_data"]["id"] == "Bin1"
end

EDIT for additional question in the comment:

API_response["response"]["bins_packed"].each_with_object([]) do |item, arr|
  arr << item["bin_data"]["weight"] if item["bin_data"]["id"] == "Bin1"
end

Upvotes: 2

jvillian
jvillian

Reputation: 20263

This is the same answer as Marcin Kolodziej with just a note that if you tag with_indifferent_access onto the end of your API_response, like this:

API_response = {
  "response"=>{
    ...
  }
}.with_indifferent_access

Then you can use symbols instead of strings as your keys (which I tend to prefer) like this:

API_response[:response][:bins_packed].count do |item|
  item[:bin_data][:id] == "Bin1"
end

If you don't like all those brackets (which I tend not to because it slows down my typing), you could do:

API_response.dig(:response, :bins_packed).count do |item|
  item.dig(:bin_data, :id) == "Bin1"
end

If, for some reason you might ever have missing keys for :response or :bins_packed (in which case dig will return nil and .count will throw an error), you could do

(API_response.dig(:response, :bins_packed) || []).count do |item|
  item.dig(:bin_data, :id) == "Bin1"
end

Which will return 0 in the case of missing keys. That seems very unlikely, but I thought I would mention it anyway.

Upvotes: 1

Related Questions