【问题标题】:Search a JSON Response with Ruby and Count Occurances使用 Ruby 搜索 JSON 响应并计算出现次数
【发布时间】:2019-03-02 19:34:20
【问题描述】:

今天我似乎无法解决以下问题。我正在解析来自 API 的 JSON 响应,该 API 可帮助我计划我的物品将装满多少箱以完成装运。

我已将来自 API 的 JSON 响应保存并解析为下面 Rails 中名为 API_response 的变量。现在,我特别需要计算每次"id"=>"Bin1" 出现在此响应中。

我在想,也许最好的方法是选择 "id"=>"Bin1" 并将其每次映射到一个数组,然后计算数组中的索引数,以便我有一个最终计数我会用多少个盒子?我该怎么做呢?

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"=>[]}}

更新 我认为我真正喜欢做的是,对于 Bin1 的每次出现,将 bin 的权重推入一个新数组。所以我希望我上面的响应示例的最终结果是一个数组,例如Bin1_Array = [80, 80, 80]

【问题讨论】:

  • 你需要Bin1出现的次数,还是当id等于Bin1items数组大小的总和?

标签: ruby-on-rails arrays json api hash


【解决方案1】:

假设您的示例只需要数字 3

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

编辑评论中的其他问题:

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

【讨论】:

  • 啊!非常感谢马尔辛。我正在用头撞墙,试图找出最好的方法。像这样在一个块中进行操作非常简单。干杯!
  • 哦,实际上是 Marcin,除了计算出现次数之外,我还想做以下事情:对于每次出现的 'Bin1',我想推送每个 Bin1 的权重(在这种情况下都是"weight"=&gt;80)到一个新数组。所以使用上面的响应,我想得到这个结果:Bin1= [80, 80, 80]
  • 惊人的@Marcin!我想我对如何从这些 JSON 响应中选择我需要的内容有了更深入的了解,因为您已经向我展示了如何通过您的编辑来做到这一点。再次感谢,您是救生员。
【解决方案2】:

这与 Marcin Kolodziej 的答案相同,只是请注意,如果您将 with_indifferent_access 标记到 API_response 的末尾,如下所示:

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

然后你可以使用符号而不是字符串作为你的键(我倾向于这样):

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

如果您不喜欢所有这些括号(我倾向于不喜欢,因为它会减慢我的打字速度),您可以这样做:

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

如果由于某种原因您可能缺少 :response 或 :bins_packed 的键(在这种情况下,dig 将返回 nil.count 将引发错误),您可以这样做

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

在缺少键的情况下将返回0。这似乎不太可能,但我想我还是会提到它。

【讨论】:

  • 这也很棒!不那么害怕这会引发错误,因为我在通话中有错误处理,但感谢您向我展示了如果不是真的如何处理这种情况!
【解决方案3】:

你可以试试这个:

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

这里group_by会对["bin_data"]["id"]的元素进行分组,一旦我们分组我们就可以很容易的得到特定key的分组数。

【讨论】:

    猜你喜欢
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 2020-02-06
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多