2016-11-19 12 views
1

marketName == 'Moneyline'を持つすべての市場からすべてmarketIDを抽出します。 .maps、.rejects、および/または.selectsのいくつかの組み合わせを試しましたが、複雑な構造が私を混乱させるので、それを絞り込むことはできません。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' 

は他とMoneyline市場からのすべてのmarketIdとの単純な配列を取得します情報は十分です。 Railsメソッドを使用することは、あまり好ましくない場合もあります。

私の編集が構文を乱した場合は申し訳ありません。 Here's the source。 JSONの解析後、:ではなく=>と表示されます。

ありがとうございました!

+0

外部リソースを使用しないでください。これはレールアプリの中でrubyか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

ちょっと@エリック・デュミル、余裕があれば、ここでもっと挑戦的な脳ティーザーがあります。出典: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' OR OR 'eventName.include?( '@')' ( '@'の前後の 'スペース')。私は 'map'と' select'の異なるコンボを試しましたが、いくつかのノードは物事を複雑にする 'countryCode'を持っていません。これらの最後の2つの基準といくつかの重複があるので、 'uniq'が必要かもしれませんか? TIA! – iamse7en

+1

別の質問をお書きください。 –

1

を、ここregexenと別の可能な答えは、この時間です。それは短くなりますが、入力データに応じて壊れる可能性があります。 jsonデータを直接Stringとして読み込みます。

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 

他の回答と同じ結果が出力されます。

関連する問題