【问题标题】:Ruby array constructionRuby数组构造
【发布时间】:2015-08-18 20:03:38
【问题描述】:

我有以下 json,

{
    "items": [
        {
            "name": "table",
            "item_group": [
                {
                    "code": "code1",
                    "section": [
                        {                         
                            "unit": "centimeter",
                            "values": [
                                {
                                    "display": "151.13 centimeter"
                                }
                            ]
                        },
                        {                         
                            "unit": "centimeter (qualifier value)",
                            "values": [
                                {
                                    "display": "170.39 centimeter"
                                }
                            ]
                        }
                    ],
                    "total": 2
                }
            ],
            "more_results": false,
            "total": 1
        }
    ]
}

我如何遍历它并创建一个“值”数组。我想要 [151.13 厘米,170.39 厘米,....] 之类的东西。请指出一些方向。谢谢。

注意:我必须在 Haml 中执行此操作。

【问题讨论】:

  • 你可以这样做:json.scan(/\"display\": \"(\d+\.\d+) centimeter/).flatten.map(&:to_f) #=> [151.13, 170.39] .
  • 您知道结构(即嵌套键等)还是只想挖掘嵌套的哈希和数组,直到找到看起来像您想要的字符串?
  • 我建议你用单引号将你的 JSON 字符串括起来,这样它就是一个。
  • 你为什么要在haml中这样做?你不能在控制器中转移这个逻辑,然后在haml中传递一个变量吗?

标签: ruby-on-rails arrays ruby json haml


【解决方案1】:

我知道有多种方法可以做到这一点。但是如果你真的有很多复杂的 JSON 查询,你可以试试ruby-jq gem。它非常快,因为它使用 linux 管道

require 'jq'
require 'jq/extend'
json_content =         {
        "items": [
            {
                "name": "table",
                "item_group": [
                {
                        "code": "code1",
                        "section": [
                            {                         
                                "unit": "centimeter",
                                "values": [
                                    {
                                        "display": "151.13 centimeter"
                                    }
                                ]
                            },
                            {                         
                                "unit": "centimeter (qualifier value)",
                                "values": [
                                    {
                                        "display": "170.39 centimeter"
                                    }
                                ]
                            }
                        ],
                        "total": 2
                    }
                ],
                "more_results": false,
                "total": 1
            }
        ]
    }


jq_filter = ' .items | .[].item_group |.[].section| . [ ] .values | . [ ] .display'

final_array = json_content.jq(jq_filter)

  # => final_array =  ["151.13 centimeter", "170.39 centimeter"]

【讨论】:

  • 这很有趣,@Amit。注意你可以写json_content.jq(jq_filter).map(&:to_f) #=> [151.13, 170.39],因为"151.13 my dog has fleas".to_f #=> 151.13
【解决方案2】:

假设你知道底层哈希的结构,你可以这样做:

代码

require 'json'

JSON.parse(json_str)['items'].each_with_object([]) do |g,arr|
  g['item_group'].each do |gg|
    gg['section'].each do |ggg|
      ggg['values'].each { |gggg|arr << gggg['display'][/\d+\.\d+/].to_f }
    end
  end
end    
  #=> [151.13, 170.39] 

说明

步骤如下:

a = JSON.parse(json_str)
b = a['items']
enum = b.each_with_object([])
  #=> #<Enumerator: [{"name"=>"table",..."total"=>1}]:each_with_object([])> 

我们可以通过将枚举器转换为数组来查看它的元素:

enum.to_a
  #=> [[{"name"=>"table", "item_group"=>[{"code"=>"code1",
  #        "section"=>[{"unit"=>"centimeter",
  #        "values"=>[{"display"=>"151.13 centimeter"}]},
  #        { "unit"=>"centimeter (qualifier value)",
  #        "values"=>[{"display"=>"170.39 centimeter"}]}], "total"=>2}],
  #     "more_results"=>false,
  #     "total"=>1},
  #   []]] 

请注意,这个数组有一个元素,一个包含哈希的二元素数组和一个空数组。

enum 的第一个元素被传递给块并使用并行赋值分配给块变量:

g, arr = enum.next
  #=> {"name"=>"table",
  #    "item_group"=>[
  #      {"code"=>"code1",
  #      "section"=>[
  #        {"unit"=>"centimeter",
  #         "values"=>[
  #           {"display"=>"151.13 centimeter"}
  #         ]
  #        },
  #      {"unit"=>"centimeter (qualifier value)",
  #      "values"=>[
  #        {"display"=>"170.39 centimeter"}
  #       ]
  #      }
  #     ],
  #    "total"=>2}],
  #    "more_results"=>false,
  #    "total"=>1} 
arr #=> [] 

c = g['item_group']
  #=> [{"code"=>"code1",
  #     "section"=>[
  #       {"unit"=>"centimeter",
  #        "values"=>[
  #          {"display"=>"151.13 centimeter"}
  #         ]
  #       },
  #       {"unit"=>"centimeter (qualifier value)",
  #        "values"=>[
  #          {"display"=>"170.39 centimeter"}
  #        ]
  #       }
  #   ],
  #   "total"=>2}] 

注意c 的格式为[hash]

c 的第一个(也是唯一一个)元素被传递给它的块并分配给它的块变量:

gg = c.first
d = gg['section']
  #=> [{"unit"=>"centimeter",
        "values"=>[
         {"display"=>"151.13 centimeter"}
        ]
       },
       {"unit"=>"centimeter (qualifier value)",
        "values"=>[
          {"display"=>"170.39 centimeter"}
        ]
       }
      ] 

ggg = d.first
  #=> {"unit"=>"centimeter",
  #    "values"=>[
  #      {"display"=>"151.13 centimeter"}
  #    ]
  #   } 

e = ggg['values']
  #=> [{"display"=>"151.13 centimeter"}]

gggg = e.first
  #=> {"display"=>"151.13 centimeter"} 

f = gggg['display']
  #=> "151.13 centimeter" 
g = f[/\d+\.\d+/]
  #=> "151.13" 
i = g.to_f
  #=> 151.13 
arr << i
  #=> [151.13] 
arr
  #=> [151.13] 

其余的计算类似。

另一种表达方式

如示例中所示,如果数组 JSON.parse(json_str)['items']g['item_group']ggg['values'] 各包含一个元素(散列),则可以改为:

JSON.parse(json_str)['items'].first['item_group'].first['section'].
  each_with_object([]) do |g, arr|
    arr << g['values'].first['display'][/\d+\.\d+/].to_f
  end
  #=> [151.13, 170.39] 

虽然我怀疑这会显着提高效率。

【讨论】:

  • 是的,我已经在一个对象中有“item_group”。所以我想遍历它并将所有“值”添加到一个数组中。
  • 不是三个循环,我们可以说 g['item_group']['section']['values'] 吗?
  • 问题是我在 Haml 中使用这个
  • 您可能只需要一个循环,请参阅我的编辑。正如我所提到的,这不太可能显着提高该方法的效率,但减少循环可能对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多