Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 在访问散列中的散列时,如何处理潜在错误?_Ruby_Hash - Fatal编程技术网

Ruby 在访问散列中的散列时,如何处理潜在错误?

Ruby 在访问散列中的散列时,如何处理潜在错误?,ruby,hash,Ruby,Hash,有时,在处理API响应时,我会编写如下内容: what_i_need = response["key"]["another key"]["another key 2"] 问题是,如果缺少另一个键,它将抛出一个错误。我不喜欢那样。如果我需要什么在过程中出现了nil,我会高兴得多 是否有比以下更优雅的解决方案: what_i_need = nil begin what_i_need = response["key"]["another key"]["another key 2"] rescue

有时,在处理API响应时,我会编写如下内容:

what_i_need = response["key"]["another key"]["another key 2"]
问题是,如果缺少另一个键,它将抛出一个错误。我不喜欢那样。如果
我需要什么
在过程中出现了
nil
,我会高兴得多

是否有比以下更优雅的解决方案:

what_i_need = nil
begin
  what_i_need = response["key"]["another key"]["another key 2"]
rescue Exception => e
end
我还考虑了monkey patching NilClass,如果您尝试访问
nil[“something”]
,它将返回
nil
,但我不确定这是否是最好的方法,如果可能的话。

使用默认值

h = {:a => 2}
h.fetch(:b,"not present")
# => "not present"
h.fetch(:a,"not present")
# => 2
如果没有默认值,它将抛出
KeyError

h = {:a => 2}
h.fetch(:b)
# ~> -:2:in `fetch': key not found: :b (KeyError)
但是使用嵌套的
散列
,您可以使用:

h = {:a => {:b => 3}}
val = h[:a][:b] rescue nil # => 3
val = h[:a][:c] rescue nil # => nil
val = h[:c][:b] rescue nil # => nil

Ruby 2.0拥有
NilClass\to\u h

what_i_need = response["key"].to_h["another key"].to_h["another key 2"]
要展开一点,可以使用的链而不是返回空哈希,直到到达链中的最后一个,然后返回
nil

what_i_need = response.fetch('key', {})
                      .fetch('another key', {})
                      .fetch('another key 2', nil)
或者依赖于引发的KeyError异常(可能不是最好的,因为应该避免控制流异常):


从Objective-C的键值编码系统中得到一些启发,您可以使用轻量级DSL在任意嵌套的数据结构中遍历一系列键:

module KeyValue
  class << self
    def lookup(obj, *path)
      path.inject(obj, &:[]) rescue nil
    end
  end
end

h = { a: { b: { c: 42, d: [ 1, 2 ] } }, e: "test"}

KeyValue.lookup(h, :a, :b, :d, 1) # => 2
KeyValue.lookup(h, :a, :x)        # => nil

。如果您没有使用异常
e
,那么就没有必要编写
=>e
。如果您使用的是
rescue
,那么就没有特别的理由从
Hash[]
切换到
Hash#fetch
,这将使您的第二个解决方案与OPs相同。OK。我明白你的意思。你认为援救<代码> KeyError <代码>比拯救<代码>异常< /代码>好。但是,即使只是StandardError,也可能会发生大量其他异常,您可能不想挽救这些异常。@AndrewMarshall我很喜欢您的
Hash#fetch
实现。这很酷。为什么在这种情况下,开始救援是件坏事?什么是使用being rescue的好地方?你可以把它写得更短:
array.inject(h,&:[])rescue nil
@sawa在这种情况下,接收器将是路径中的元素,而不是散列?@naomik是的。这是一个很酷的功能。您可以对数组执行类似的操作,如
array[0]。to_a[1]
to_a
to_h
名称的原因是什么?它们看起来不太合适。我希望像
try\u a
try\u h
这样的事情总会成功
to_a
总是将某物转换为数组
to_h
总是将某些内容转换为散列。哇,以前从未见过您的上一个示例。我总是有
。到处试试
module KeyValue
  class << self
    def lookup(obj, *path)
      path.inject(obj, &:[]) rescue nil
    end
  end
end

h = { a: { b: { c: 42, d: [ 1, 2 ] } }, e: "test"}

KeyValue.lookup(h, :a, :b, :d, 1) # => 2
KeyValue.lookup(h, :a, :x)        # => nil
(["key", "another key", "another key 2"].inject(h, &:[]) rescue nil)