通过迭代嵌套哈希来构建新哈希

时间:2011-08-22 15:29:36

标签: ruby hash nested

所以我正在尝试重新整理Google Places API中的一些数据,目前它来自这样的API:

{"results"=> [
             {"geometry"=>{"location"=>{"lat"=>51.503815, "lng"=>-0.11007}}, "icon"=>"http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png", "id"=>"5f212d158f4181db3ac0619fb3c52f36d4e276c2", "name"=>"Madeira Cafe", "reference"=>"CnRjAAAApaZWmTl5wOMtW49q3D1BLKAJ_M8lmZxaD6_-AU92qWfVZdokfTWOzlp5En_r9hSUHx-EeP71hzH7iDPYAGPtiqEAXvT4WcI3xlc5XUivenbQLw0j5MHW-ErL-Hbk4xB_by0OSsXCz9etNgkjbp0QCRIQ82Dgj-I3DAJqr7I3EwsFEhoUm2RXf2rCFlSuhfKjSsPuWKA2VGA",     {"results"=> [{"geometry"=>{"location"=>{"lat"=>51.503815, "lng"=>-0.11007}},
              "icon"=>"http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
              "id"=>"11111111",
              "name"=>"Madeira Cafe",
              "reference"=>"xxxxx",
              "types"=>["restaurant", "food", "establishment"],
              "vicinity"=>"London"}]}

将结果放入具有一个键值的哈希 - "results"

其余的数据是嵌套的内部(我认为),"geometry"是每条记录的第一个。

我想要的是一个整洁的哈希,每个地方都有一个ID,Lat / Lng和Name存储...所以它可以存储和查询。

我尝试过这样的事情:

results_hash = {}
result.each do |geometry, location, id|
  results_hash[id] = geometry
end

p results_hash  

但我无法让它工作......它总是输出nil或只是相同的哈希值?

我希望这是有道理的,如果有人只是说“读这个”它仍然是一个很好的帮助。

谢谢!

查理

3 个答案:

答案 0 :(得分:4)

听起来你想要这个:

results_hash = result["results"].inject({}) { |h, res| h[res["id"]] = res["geometry"]; h }

这会为您提供以下哈希值(使用awesome_print打印):

{
    "2d48a3306535b60663645323cdf972c320da8b9d" => {
        "location" => {
            "lng" => -0.114522,
            "lat" => 51.502653
        }
    },
    "5f212d158f4181db3ac0619fb3c52f36d4e276c2" => {
        "location" => {
            "lng" => -0.11007,
            "lat" => 51.503815
        }
    }
}

你可能想要稍微更好地格式化它:

results_hash = result["results"].inject({}) do |h, res| 
  h[res["id"]] = res["geometry"]
  h
end

或者如果您使用的是1.9:

results_hash = result["results"].each_with_object({}) do |res, h| 
  h[res["id"]] = res["geometry"]
end

答案 1 :(得分:0)

你所拥有的是一系列哈希,即[{:geometry => ......,:id => ...},{:geometry => ......,:id => ......}等等。我将提取数组,然后使用Enumerable#inject方法迭代数组中的每个元素(即数组中的每个元素都是一个哈希),并在你去的时候构建一个新的哈希。

达到以下程度:

# locations_array is [{"geometry"=>..., "icon"=>..., "id"=>..., etc}, {"geometry"=>..., "icon"=>..., "id"=>..., etc}, etc]
results_hash = locations_array.inject({}) do |hash, element|
  # extract the id key and the long/lat values
  # store them in the new hash
  hash[element[:id]] = element[:geometry]
  hash
end

答案 2 :(得分:0)

如果你想要一个ID为lat,lon和name的地方哈希,你可以这样做:

result_hash = {}
hash_from_google["results"].each do |result|
  result_hash[result["id"]] = {
    :name => result["name"], 
    :latitude => result["geometry"]["location"]["lat"],
    :longitude => result["geometry"]["location"]["lng"]
  }
end

现在你的结果看起来像这样:

result_hash["5f212..."] => {:name => "Madeira Cafe", :latitude => 51...., :longitude => -0.1....}

基本上,只需从您从Google Places API获取的哈希中解析出您需要的内容。如果您在确定如何设置数据或类似的问题时遇到问题,请尝试将其复制到IRB并使用它 - 执行类似的操作可以很容易地找出哈希的结构。