2016-11-19 79 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 

它輸出與其他答案相同的結果。