【问题标题】:Ruby: Extract from deeply nested JSON structure based on multiple criteriaRuby:基于多个标准从深度嵌套的 JSON 结构中提取
【发布时间】:2016-11-21 04:24:40
【问题描述】:

我想选择marketName == 'Moneyline' 中的任何marketId,但只选择countryCode == 'US' || 'GB'eventName.include?(' @ ') 的那些。 (space@ 之前和之后)。我尝试了不同的 map 和 select 组合,但有些节点没有 countryCode,这让我的事情变得复杂。 This 是来源,但它可能看起来像一个示例:

{"currencyCode"=>"GBP",
"eventTypes"=>[
    {"eventTypeId"=>7522,
    "eventNodes"=>[
        {"eventId"=>28024331,
        "event"=>
            {"eventName"=>"EWE Baskets Oldenburg v PAOK Thessaloniki BC"
            },
            "marketNodes"=>[
                {"marketId"=>"1.128376755",
                "description"=>
                    {"marketName"=>"Moneyline"}
                },
                {"marketId"=>"1.128377853",
                "description"=>
                    {"marketName"=>"Start Lublin +7.5"}
                }}}]},
        {"eventId"=>28023434,
        "event"=>
            {"eventName"=>"Asseco Gdynia v Start Lublin",
            "countryCode"=>"PL",
            },
            "marketNodes"=>
                [{"marketId"=>"1.128377853", ETC...

【问题讨论】:

  • 尝试使用递归?稍后我会写一个完整的答案...
  • 也可以使用json路径
  • 当你给出一个例子时,请执行以下操作。 1. 使其成为有效的 Ruby 对象(没有“ETC...”),以便读者可以针对您的示例运行他们的代码。 2. 显示所需的返回值。 3. 通过去除无关元素来简化示例。由于hash = JSON.parse(File.read('data.json')) 很明显,因此您可能只想显示哈希而不是 JSON 字符串,并且不引用 JSON。 4. 为每个输入对象分配一个变量(例如,h = {currency...})。这使读者可以在答案和 cmets 中引用这些变量,而无需定义它们。

标签: json ruby hash


【解决方案1】:

基于之前的answer,你只需要在eventNodes上添加一个select:

require 'json'

json = File.read('data.json')
hash = JSON.parse(json)

moneyline_market_ids = hash["eventTypes"].map{|type|
  type["eventNodes"].select{|event_node|
    ['US', 'GB'].include?(event_node["event"]["countryCode"]) || event_node["event"]["eventName"].include?(' @ ')
  }.map{|event|
    event["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

如果你想用id保留国家代码和名称信息:

moneyline_market_ids = hash["eventTypes"].map{|type|
  type["eventNodes"].map{|event_node|
    [event_node, event_node["event"]["countryCode"], event_node["event"]["eventName"]]
  }.select{|_, country, event_name|
    ['US', 'GB'].include?(country) || event_name.include?(' @ ')
  }.map{|event, country, event_name|
    event["marketNodes"].select{|market|
      market["description"]["marketName"] == 'Moneyline'
    }.map{|market|
      [market["marketId"],country,event_name]
    }
  }
}.flatten(2)

require 'pp'
pp moneyline_market_ids
#=> [["1.128255531", "US", "Philadelphia @ Seattle"],
#   ["1.128272164", "US", "Arkansas @ Mississippi State"],
#   ["1.128255516", "US", "New England @ San Francisco"],
#   ["1.128272159", "US", "Indiana @ Michigan"],
#   ["1.128278718", "CA", "Edmonton @ Ottawa"],
#   ["1.128272176", "US", "Arizona State @ Washington"],
#   ["1.128272174", "US", "Alabama A&M @ Auburn"],
#    ...

【讨论】:

  • 谢谢!我自己非常接近这一点,但不断收到语法错误。欣赏它。
  • 哇,第二个可能真的很方便......谢谢你加倍努力!
猜你喜欢
  • 2017-04-03
  • 1970-01-01
  • 2021-07-18
  • 2020-03-19
  • 1970-01-01
  • 2014-11-08
  • 2020-11-07
  • 2012-09-16
  • 2019-03-15
相关资源
最近更新 更多