如果OpenStruct中不存在密钥,我如何返回nil



我有一个散列,它被传递给OpenStruct,以便使其与.形成单词。这非常有效。但当我试图访问一个不存在的密钥时,就会引发undefined method <unknown key> for #<Hash:0x7f24ea884210> (NoMethodError)。如何使其返回nil

如果我对原始哈希尝试相同的操作,我会得到nil,但不会得到OpenStruct!!

程序片段:

TXT_HASH = load_data("test.txt")
pp TXT_HASH[:ftp][:lastname]  ## print nil as lastname does not exist
TXT = OpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname  ## raises NoMethodError ## Can it return nil?

OpenStruct不是递归的。在这种情况下,TXT.ftp返回的是Hash,而不是OpenStruct,因此没有定义#lastname

如果你愿意的话,有一个叫做递归开放结构的库。这样使用:

require 'recursive-open-struct'
TXT = RecursiveOpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname #=> nil

@Shel给出的答案是最好的,简单明了。

注意:
如果您不想需要不必要的库,那么还有另一种变通方法可以实现
是的,OpenStruct不是递归的,但我们可以创建自己的递归方法来做到这一点

# This method is kind of factory to create OpenStruct instances
def get_recursive_ostruct(object)
  if object.is_a?(Hash) 
    object = object.clone
    object.each do |key, value|
      object[key] = get_recursive_ostruct(value)
    end
    OpenStruct.new(object)
  else
    object
  end
end

并使用这种方法

require 'ostruct'
hash = {first: 'this is first', second: {first: 'first of second', second: 'second of second'}}
obj = get_recursive_ostruct(hash)
#=>  #<OpenStruct first="this is first", second=#<OpenStruct first="first of second", second="second of second">> 
obj.second.second
#=> "second of second" 
obj.second.third
#=> nil 

此外,若您希望对象不返回异常,那个么也有一些解决方法。

TXT.ftp.lastname  ## raises NoMethodError 
TXT.ftp.try(:lastname)  ## returns nil if `lastname` is not available
TXT.try(:ftp).try(:lastname)  ## returns nil even if `ftp` is not available

注意:
据我所知,try方法仅在Rails应用程序中可用,而在IRBruby应用程序中不可用。

我会使用:rescue方法
注意:此方法捕获异常并做出相应响应;如果您需要以不同的方式响应异常,请不要使用此选项。我希望你了解

TXT.ftp.lastname rescue nil # respond with default value i.e. nil
TXT.ftp.lastname rescue '' # respond with default value i.e. ''

如果你想要一个递归的OpenStruct,另一种选择是使用哈希宝石中的Mash:

require 'hashie'
text = Hashie::Mash.new(text_hash)
p text.ftp.lastname #=> nil

最新更新