0

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]

1
  • Do you need the number of times Bin1 occurs, or the sum of size of items array for when the id equals Bin1? Commented Sep 27, 2018 at 0:24

3 Answers 3

2

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
Sign up to request clarification or add additional context in comments.

3 Comments

Ah! Thank you so very much Marcin. I was beating my head against a wall trying to figure out the best way. Doing it in a block like this is incredibly simple. Cheers!
Oh, actually Marcin, in addition to counting the number of occurrences, I'd also like to maybe do the following, too: for each occurrence of 'Bin1', I'd like to push the weight of each Bin1 (in this case all of them are "weight"=>80) to a new array. So using the response above, I'd like to get this result: Bin1= [80, 80, 80]
Amazing @Marcin! I think I have a much more firm understanding of how to select what I need from these JSON responses now that you've shown me how to do it with your edit. Thanks again, you're a lifesaver.
1

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.

1 Comment

This is great too! Not so fearful of this throwing an error as I have error handling on the call, but thanks for showing me how to handle this situation if that were not true!
0

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.

Comments

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.