我需要了解data[i][j][k]
元素是否存在,但我不知道data[i]
或data[i][j]
是否自己为零。
如果我只是data[i][j][k].nil?
,如果data [i]或data [i] [j]为undefined method [] for nil:NilClass
,则会抛出nil
所以,我现在正在使用
unless data[i].nil? or data[i][j].nil? or data[i][j][k].nil?
# do something with data[i][j][k]
end
但它有点麻烦。
有没有其他方法可以检查data[i][j][k]
是否存在data[i].nil? or data[i][j].nil? or data[i][j][k].nil?
?
答案 0 :(得分:3)
我通常会这样做:
unless (data[i][j][k] rescue false)
# do something
end
答案 1 :(得分:2)
您可以略微缩短为
if data[i] && data[i][j] && data[i][j][k]
# do something with data[i][j][k]
end
你也可以使用“andand”gem来编写:
data[i].andand[j].andand[k]
如果你愿意使用补丁Array
,你可以定义一个启用此功能的方法,例如:
class Array
def index_series(*args)
result = self
args.each do |key|
result = result[key]
return nil if result.nil?
end
result
end
end
可以让你这样做:
data.index_series(i, j, k)
答案 2 :(得分:2)
以下是三种不同的选择:
您可以使用“!
”代替.nil?
来缩短它:
!data[i] or !data[i][j] or !data[i][j][k]
你可以通过这样做来摆脱重复:
((data[i] || [])[j] || [])[k].nil?
上面的两个代码片段都很讨厌,我可能不会在代码库中多次编写它们。
三维数组看起来很复杂,你不应该直接在代码中的很多地方访问它。您应该考虑将其包装在具有适当名称的对象中:
class My3DWorld
def initialize
# set up @data
end
# Gets the point or returns nil if it doesn't exist.
def get_point(i, j, k)
@data[i] && @data[i][j] && @data[i][j][k]
end
end
然而,最终,我想知道你是否真的需要一个3D阵列。实现这种数据结构的另一种类似Ruby的方法是使用散列并使用i,j,k坐标元组作为键。除非这是一个庞大的结构,并且您需要3D阵列的性能特征,我建议在这里查看我的其他答案:
答案 3 :(得分:2)
新功能“改进”是一个选项:
module ResponsiveNil
refine NilClass do
def [](obj)
nil
end
end
end
using ResponsiveNil
a = [[1]]
p a[2][3][4] #=> nil
答案 4 :(得分:0)
以下内容允许任意数量的嵌套,并允许数组元素的值为nil
:
def element_exists?(arr, *indices)
if arr.is_a? Array
return true if indices.empty?
return false if arr.size <= (i = indices.pop)
element_exists?(arr[i], *indices)
else
indices.empty?
end
end
data = [[0,1],[2,nil]]
element_exists?(data) # => true
element_exists?(data, 1) # => true
element_exists?(data, 2) # => false
element_exists?(data, 1, 1) # => true
element_exists?(data, 1, 2) # => false
element_exists?(data, 1, 1, 1) # => false