访问嵌套数组,其中深度未知,直到Ruby中的运行时

时间:2014-08-31 01:52:07

标签: ruby arrays types tree nested

示例:

array = [ [ [ [ ["foo"] ] ] ] ]
array[0][0][0][0][0] == "foo" # => true

在这种情况下,我知道数组的深度是5,所以我可以使用 array[0][0][0][0][0]访问其中的内容。 我的问题是:如果我有depth = ?,每次程序运行时?都不同,我如何在Ruby中访问(写入)嵌套数组中的元素。 (我假设每个数组只有一个子数组)。

3 个答案:

答案 0 :(得分:3)

你需要一个递归函数:

def innermost(x)
  (x.is_a? Array) ? innermost(x[0]) : x
end

array = [ [ [ [ ["foo"] ] ] ] ]
innermost(array)
# => "foo"

<强>更新

更新后的版本返回最里面的数组而不是数组的元素。

def innermost(x)
  (x[0].is_a? Array) ? innermost(x[0]) : x
end

array = [ [ [ [ ["foo"] ] ] ] ]
a = innermost(array)  # => ["foo"]
a[0] = 'bar'
array
# => [[[[["bar"]]]]]

答案 1 :(得分:2)

如果数组只包含一个数据,则可以使用flatten。

array = [ [ [ [ ["foo"] ] ] ] ]
array.flatten[0]
 => "foo"

答案 2 :(得分:0)

[编辑:我试图太可爱了,它咬了我一下。最初我提出了两种使用array.to_s[/\[+/].size确定级别数的方法。使用eval将字符串转换为输出数组的方法之一。 @FrederickCheung指出了两个瑕疵(谢谢,弗雷德里克),你可以在评论中看到。如果您想查看我的原始答案,您当然可以查看编辑内容。我现在编辑了建议我最初提出的第一种方法的更传统的变体。的

这是一种非递归方法。

def replace_foo(array, val) 
  a = array
  nbr_levels = (1..Float::INFINITY).find { |i| !(a=a.first).is_a? Array }
  nbr_levels.times.reduce(val) { |a,_| [a] }
end

array = [ [ [ [ ["foo"] ] ] ] ]
  #=> [[[[["foo"]]]]]

replace_foo(array, { our_dog: "Diva", our_cat: "Teagan" })
  #=> [[[[[{:our_dog=>"Diva", :our_cat=>"Teagan"}]]]]]