Ruby 逻辑OR的替代方案,其中false被视为truthy?
所以我有一些代码,它们以固定的优先级顺序从几个源中获取值。看起来是这样的:Ruby 逻辑OR的替代方案,其中false被视为truthy?,ruby,Ruby,所以我有一些代码,它们以固定的优先级顺序从几个源中获取值。看起来是这样的: { foo: true bar: 42 }.each_pair do |attrib,default| instance_variable_set :"@#{attrib}",data[attrib] || template[attrib] || otherdata[attrib] || default end 正如您可能知道的,尝试用false覆盖true默认值是行不通的。我如何在不造成可怕混乱的
{ foo: true
bar: 42
}.each_pair do |attrib,default|
instance_variable_set :"@#{attrib}",data[attrib] || template[attrib] || otherdata[attrib] || default
end
正如您可能知道的,尝试用false覆盖true默认值是行不通的。我如何在不造成可怕混乱的情况下解决这个问题?(我确实知道如何用一团乱麻来修复它,但我相当肯定标准库中有适合这种情况的东西,我只是不记得它叫什么,也想不出一个好的搜索词)如果您正在寻找第一个非
nil
值:
instance_variable_set :"@#{attrib}", [ data[attrib], template[attrib], otherdata[attrib], default ].compact.first
这不是最有效的方法,但如果不积极地锻炼,就可以完成工作,效果很好
稍微宽容一点的版本:
instance_variable_set :"@#{attrib}", [ data[attrib], template[attrib], otherdata[attrib], default ].find { |v| !v.nil? }
这将扫描第一个非nil值并返回该值。它不会像compact
那样生成中间数组
你真正想要的是一种更宽容的方法:
def instance_variable_set_from(attrib, *sources)
instance_variable_set(:"@#{attrib}", sources.find { |v| !v.nil? }
end
使用时,以下哪一项更容易解释:
instance_variable_set_from(attrib, data[attrib], template[attrib], otherdata[attrib], default)
假设
数据
,模板
和其他数据
都是散列,您可以使用。如果该值包含在哈希中,则返回该值,否则返回块的结果:
value = data.fetch(attrib) { template.fetch(attrib) { otherdata.fetch(attrib, default) } }
instance_variable_set :"@#{attrib}", value
或者,包含键和获取其结果的第一个哈希,返回到默认值
:
value = [data, template, other_data].find { |h| h.key?(attrib) }.fetch(attrib, default)
请注意,这也将允许nil
值。实际上不会给出相同的短路评估,但比我想象的要干净得多。散列查找速度非常快,因此非常方便。是的,另一种方法是data[attrib].nil?模板[attrib].nil???:模板[attrib]:数据[attrib]
,它确实不那么可读。有人说Ruby引入了一个与|
操作相同的/
操作符,但只在nil
上使用,不知道这是怎么回事。