我确信之前我已经看到了一个优雅的解决方案,但我找不到它:
我有一个rails控制器,可能或者可能没有以下哈希元素:
myhash[:parent_field]
在该父字段内,子元素也可以为空。我目前正在通过(非常难看的)方法检查它:
if (!myhash[:parent_field] || !myhash[:parent_field][:child_field] || myhash[:parent_field][:child_field].blank?)
哪个有效,但我认为 - 当然 - 必须有更优雅的方式。只是重申:
答案 0 :(得分:9)
#fetch
是你的朋友:
my_hash.fetch(:parent, {})[:child].blank?
答案 1 :(得分:3)
我会做什么只是使用局部变量来减轻负担:
unless (p=foo[:parent]) && (c=p[:child]) && !c.blank?
# Stuff is borked!
end
但是,为了好玩,让我们探索替代方案......
如果您无法更改数据结构(顺便说一下,这不是数组),那么您可以将Ruby andand gem与Rails'try
结合使用在可能是nil
个对象的事物上调用方法的方法。
当您要求输入不存在的密钥时,您也可以将数据结构更改为返回空的自动生成哈希值的哈希值:
mine = Hash.new{ |h,k| Hash.new(&h.default_proc) }
mine[:root] = { dive:42 }
p mine[:root][:dive] #=> 42
p mine[:ohno][:blah][:whee] #=> {}
p mine[:root][:blah][:whee] #=> undefined method `[]' for nil:NilClass (NoMethodError)
但是,您必须确保层次结构中的每个对象都是其中一个哈希值(我明确无法对:dive
的内容执行此操作,从而导致错误)。
为了另类乐趣,您可以添加自己的魔术查找方法:
class Hash
def divedive(*keys)
obj = self
keys.each do |key|
return obj unless obj && obj.respond_to?(:[])
obj = obj[key]
end
obj
end
end
if myarray.divedive(:parent,:child).blank?
# ...
答案 2 :(得分:1)
这是一个经常被问到的问题,应该作为
的副本关闭该列表中的第一个作为另外两个的副本被关闭,但我相信我的答案比后两个更全面地解决了这个问题。
答案 3 :(得分:0)
这可能取决于您的实际需求,但是对此的OOP方法是将数组和散列转换为实际对象。每个对象都会管理它的关系(类似于ActiveRecord),并且知道如何让孩子和父母。
答案 4 :(得分:0)
由于nil.blank?
为true
,您可以删除中间条件并简化为:
if !myarray[:parent_field] || myarray[:parent_field][:child_field].blank?
另外,调用哈希myarray
有点误导。
答案 5 :(得分:-2)
怎么样
!(myarray[:parent_field][:child_field] rescue nil).blank?