Ruby:根据条件从深层嵌套的JSON结构中提取元素

想要从每个具有marketName == 'Moneyline'市场中提取每个marketID 。 尝试了.map s, .reject s和/或.select s的一些组合,但由于复杂的结构使我感到困惑,所以无法缩小范围。

活动中有许多markets ,也有很多events 。 结构样本(为简洁起见,尝试编辑):

 {"currencyCode"=>"GBP", "eventTypes"=>[ {"eventTypeId"=>6423, "eventNodes"=>[ {"eventId"=>28017227, "event"=> {"eventName"=>"Philadelphia @ Seattle" }, "marketNodes"=>[ {"marketId"=>"1.128274650", "description"=> {"marketName"=>"Moneyline"} }, {"marketId"=>"1.128274625", "description"=> {"marketName"=>"Winning Margin"} }}}]}, {"eventId"=>28018251, "event"=> {"eventName"=>"Arkansas @ Mississippi State" }, "marketNodes"=>[ {"marketId"=>"1.128299882", "description"=> {"marketName"=>"Under/Over 60.5pts"} }, {"marketId"=>"1.128299881", "description"=> {"marketName"=>"Moneyline"} }}}]}, {"eventId"=> etc.... 

尝试各种各样的事情,例如,

 markets = json["eventTypes"].first["eventNodes"].map {|e| e["marketNodes"].map { |e| e["marketId"] } if (e["marketNodes"].map {|e| e["marketName"] == 'Moneyline'})} markets.flatten # => yields every marketId not every marketId with marketName of 'Moneyline' 

从Moneyline市场获得一个简单的arrays,没有其他信息就足够了。 如果愿意,使用Rails方法也很好。

很抱歉,如果我的编辑搞砸了语法。 这是来源 。 在解析JSON之后,它看起来只有=>而不是:

谢谢!

我喜欢嵌套地图并选择:D

 require 'json' hash = JSON.parse(File.read('data.json')) moneyline_market_ids = hash["eventTypes"].map{|type| type["eventNodes"].map{|node| node["marketNodes"].select{|market| market["description"]["marketName"] == 'Moneyline' }.map{|market| market["marketId"]} } }.flatten puts moneyline_market_ids.join(', ') #=> 1.128255531, 1.128272164, 1.128255516, 1.128272159, 1.128278718, 1.128272176, 1.128272174, 1.128272169, 1.128272148, 1.128272146, 1.128255464, 1.128255448, 1.128272157, 1.128272155, 1.128255499, 1.128272153, 1.128255484, 1.128272150, 1.128255748, 1.128272185, 1.128278720, 1.128272183, 1.128272178, 1.128255729, 1.128360712, 1.128255371, 1.128255433, 1.128255418, 1.128255403, 1.128255387 

只是为了好玩,这是另一个可能的答案,这次是regexen。 它更短但可能会根据您的输入数据而中断。 它直接以字符串forms读取json数据:

 json = File.read('data.json') market_ids = json.scan(/(?<="marketId":")[\d\.]+/) market_names = json.scan(/(?<="marketName":")[^"]+/) moneyline_market_ids = market_ids.zip(market_names).select{|id,name| name=="Moneyline"}.map{|id,_| id} puts moneyline_market_ids.join(', ') #=> 1.128255531, 1.128272164, 1.128255516, 1.128272159, 1.128278718, 1.128272176, 1.128272174, 1.128272169, 1.128272148, 1.128272146, 1.128255464, 1.128255448, 1.128272157, 1.128272155, 1.128255499, 1.128272153, 1.128255484, 1.128272150, 1.128255748, 1.128272185, 1.128278720, 1.128272183, 1.128272178, 1.128255729, 1.128360712, 1.128255371, 1.128255433, 1.128255418, 1.128255403, 1.128255387 

它输出与其他答案相同的结果。