检查数组元素数据[i][j][k]是否存在



我需要找出data[i][j][k]元素是否存在,但我不知道data[i]data[i][j]本身是否为零
如果我只是data[i][j][k].nil?,如果data[I]或data[I][j]是nil,它会抛出undefined method [] for nil:NilClass

所以,我现在使用

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].nil? or data[i][j].nil? or data[i][j][k].nil?,是否有其他方法可以检查data[i][j][k]的存在?

我通常这样做:

unless (data[i][j][k] rescue false)
# do something
end

这里有三种不同的替代方案:

缩短

您可以使用"!"而不是.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阵列的性能特征,否则我建议在这里看看我的另一个答案:

https://stackoverflow.com/a/20600345/28128

新功能"精化"是一个选项:

module ResponsiveNil
refine NilClass do
def [](obj)
nil 
end
end
end
using ResponsiveNil
a = [[1]]
p a[2][3][4]  #=> nil

您可以稍微缩短为

if data[i] && data[i][j] && data[i][j][k]
# do something with data[i][j][k]
end

你也可以你的"andand"宝石,它允许你写:

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)

以下允许任何数量的嵌套,并允许数组的元素值为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 

您可以使用Array#dig:

item = data.dig(i, j, k)

如果其中一个索引无效,它将返回nil

最新更新