Reputation: 43
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
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
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
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