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

时间:2016-11-19 22:22:52

标签: arrays json ruby hash

想从每个拥有marketID的市场中提取每个marketName == 'Moneyline'。尝试了.map s,.reject和/或.select s的几种组合,但由于复杂的结构使我感到困惑,因此无法将其缩小范围。

markets中有很多events,还有很多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市场获得一个简单的阵列,没有其他信息就足够了。如果愿意,使用Rails方法也很好。

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

谢谢!

2 个答案:

答案 0 :(得分: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

答案 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

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