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

scyqe7ek  于 2023-04-20  发布在  Ruby
关注(0)|答案(6)|浏览(131)

我需要找出data[i][j][k]元素是否存在,但我不知道data[i]data[i][j]本身是否不为nil。
如果我只是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][j][k]是否存在而没有data[i].nil? or data[i][j].nil? or data[i][j][k].nil?

t1rydlwq

t1rydlwq1#

我通常这样做:

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

6tdlim6h2#

以下是三种不同的选择:

缩短

您可以使用“!”而不是.nil?来稍微缩短它:

!data[i] or !data[i][j] or !data[i][j][k]

你可以通过这样做来摆脱重复:

((data[i] || [])[j] || [])[k].nil?

抽象掉这些细节

上面的两个代码片段都很糟糕,我可能不会在代码库中多次编写它们。
一个三维数组看起来很复杂,你不应该在代码中的很多地方直接访问它。你应该考虑用一个合适的名字将它 Package 在一个对象中:

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

使用hash

然而,最终,我想知道你是否真的需要一个3D数组。另一种更像Ruby的方法来实现这个数据结构是使用哈希并使用i,j,k坐标元组作为键。除非这是一个巨大的结构,并且你需要3D数组的性能特征,我建议在这里看看我的另一个答案:
https://stackoverflow.com/a/20600345/28128

35g0bw71

35g0bw713#

新功能“改进”是一个选项:

module ResponsiveNil
  refine NilClass do
    def [](obj)
      nil 
    end
  end
end

using ResponsiveNil
a = [[1]]
p a[2][3][4]  #=> nil
dphi5xsq

dphi5xsq4#

你可以稍微缩短到

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)
6uxekuva

6uxekuva5#

下面的代码允许任意数量的嵌套,并允许数组的元素具有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
sgtfey8w

sgtfey8w6#

可以使用Array#dig

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

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

相关问题