iamse7en iamse7en - 19 days ago 5
Ruby Question

Ruby: Extract elements from deeply nested JSON structure based on criteria

Want to extract every

marketID
from every market that has a
marketName == 'Moneyline'
. Tried a few combinations of
.map
s,
.reject
s, and/or
.select
s but can't narrow it down as the complicated structure is confusing me.

There are many
markets
in
events
, and there are many
events
as well. A sample of the structure (tried to edit it for brevity):

{"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....


Tried all kinds of things, for example,

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'


Getting a simple array with every marketId from Moneyline markets with no other information is sufficient. Using Rails methods is fine too if preferred.

Sorry if my editing messed up the syntax. Here's the source. It looks like this only with
=>
instead of
:
after parsing the JSON.

Thank you!

Answer

I love nested maps and selects :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