Ruby - 验证散列键是否存在

Ruby - Verify hash key exists

我在使用嵌套哈希时遇到问题,希望得到一些帮助。我正在处理的数据如下所示:

    => {"searchresults"=>
  {"request"=>{"address"=>"10 Tiverton Ln", "citystatezip"=>"28803"},
   "message"=>{"text"=>"Request successfully processed", "code"=>"0"},
   "response"=>
    {"results"=>
      {"result"=>
        {"zpid"=>"5620805"}}

我正在尝试从哈希中获取特定信息。我遇到的问题是:如果哈希键不存在,它会抛出错误并终止我的脚本。

为了解决这个问题,我想我会事先验证密钥是否存在,但是,我的检查似乎没有正常工作。我正在使用 "key?" 方法,但我显然做错了什么,因为在我的验证中(当密钥存在时)导致 "false" 从 Ruby.[=15 返回=]

hash["searchresults"]["response"]["results"]["result"]["zpid"]
=> "5620805"
hash.key?("searchresults""response""results""result""zpid")
=> false

(注意:我意识到最后的输入只是一个基于评论的连接字符串,但无法使任何组合起作用,请参见下方 - post 的底部)

在查询不存在的哈希键时避免错误的最佳方法是什么?如果 "key?" 方法是解决此问题的正确方法,请有人指出我错误所在的正确方向。


根据回复添加了信息。我正在使用以下版本的 ruby

ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]

多亏了 comments.Everything 我终于能够理解 dig 方法的语法了……谢谢!

hash.dig("searchresults", "response", "results", "result", "zpid")
    => "5620805"
h = { "searchresults"=>
        { "request" =>{ "address"=>"10 Tiverton Ln", "citystatezip"=>"28803" },
          "message" =>{ "text"=>"Request successfully processed", "code"=>"0" },
          "response"=>{ "results"=>{
                                     "result"=>{ "zpid"=>"5620805" }
                                   }
                      }
        }
    }

正如@muistooshort 在评论中指出的那样,如果您使用 Ruby v2.3+​​,可以在此处使用 Hash#dig

h.dig("searchresults")
  #=> {"request"=>{"address"=>"10 Tiverton Ln", "citystatezip"=>"28803"},
  #    "message"=>{"text"=>"Request successfully processed", "code"=>"0"},
  #    "response"=>{"results"=>{"result"=>{"zpid"=>"5620805"}}}} 
h.dig("searchresults", "response")
  #=> {"results"=>{"result"=>{"zpid"=>"5620805"}}}
h.dig("searchresults", "response", "results")
  #=> {"result"=>{"zpid"=>"5620805"}} 
h.dig("searchresults", "response", "results", "result")
  #=> {"zpid"=>"5620805"} 
h.dig("searchresults", "response", "results", "result", "zpid")
  #=> "5620805"

h.dig("searchresults", "cat", "results")
  #=> nil
h.dig("searchresults", "response", "results", "result", "dog")
  #=> nil 

对于 Ruby 的早期版本,您可以使用 Enumerable#reduce(又名 inject)。

def my_dig(h, *keys)
  keys.reduce(h) { |g,k| g && g[k] }
end

my_dig(h, "searchresults")
  #=> {"request"=>{"address"=>"10 Tiverton Ln", "citystatezip"=>"28803"},
  #    "message"=>{"text"=>"Request successfully processed", "code"=>"0"},
  #    "response"=>{"results"=>{"result"=>{"zpid"=>"5620805"}}}} 
my_dig(h, "searchresults", "response")
  #=> {"results"=>{"result"=>{"zpid"=>"5620805"}}}
my_dig(h, "searchresults", "response", "results")
  #=> {"result"=>{"zpid"=>"5620805"}} 
my_dig(h, "searchresults", "response", "results", "result")
  #=> {"zpid"=>"5620805"} 
my_dig(h, "searchresults", "response", "results", "result", "zpid")
  #=> "5620805" 

my_dig(h, "searchresults", "cat", "results")
  #=> nil 
my_dig(h, "searchresults", "response", "results", "result", "zpid", "dog")
  #=> nil