2016-11-19 30 views
1

想要从每个有marketName == 'Moneyline'的市场中提取每个marketID。尝试了几种组合.map s,.reject s和/或.select s,但无法缩小它,因为复杂的结构令我感到困惑。Ruby:根据标准从深度嵌套的JSON结构中提取元素

events中有很多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' 

获得一个简单的数组每marketId从Moneyline市场,没有其他信息就足够了。如果喜欢,使用Rails方法也可以。

对不起,如果我的编辑搞砸了语法。 Here's the source。在解析JSON之后,它看起来像=>而不是:

谢谢!

+0

宁可不使用外部资源。这是在一个Rails应用程序,所以无论是红宝石或铁轨方法 – iamse7en

+0

你有一个正确的语法的例子吗? –

+1

@EricDuminil对不起,如果我的编辑搞砸了。看到这里:https://www.betfair.com/www/sports/exchange/readonly/v1/allmarkets?eventTypeIds=6423&types=MARKET_DESCRIPTION,EVENT&alt=json在我的控制台,它基本上看起来像只有'=>'解析后代替':'。这有点凌乱。 – iamse7en

回答

2

我爱巢地图和选择: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 
+0

yowza。完善。非常感谢你!我的头痛苦地想弄明白。 – iamse7en

+0

嘿@ eric-duminil,如果您有空余的时间,我在这里有一个更具挑战性的头脑传情。资料来源:https://www.betfair.com/www/sports/exchange/readonly/v1/allmarkets?eventTypeIds=7522&types=MARKET_DESCRIPTION,EVENT,MARKET_RATES&alt=json。我想选择'marketIds =='Moneyline',但只选择'countryCode =='US'|| 'GB'或'eventName.include?('@')'。 (在'@'之前和之后''空格')。我尝试了'map'和'select'的不同组合,但有些节点没有'countryCode',这使事情变得复杂。与最后两个标准有一些重叠,所以'uniq'可能是必需的? TIA! – iamse7en

+1

请再写一个问题。 –

1

只是为了好玩,这里是另一个可能的答案,这一次使用regexen。它更短,但可能会因您的输入数据而中断。它直接以字符串的形式读取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 

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