【问题标题】:Access nested array, where depth is unknown until runtime in Ruby访问嵌套数组,其中深度在 Ruby 中运行之前是未知的
【发布时间】:2014-08-31 01:52:06
【问题描述】:

例子:

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

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

【问题讨论】:

    标签: ruby arrays types tree nested


    【解决方案1】:

    你需要一个递归函数:

    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"]]]]]
    

    【讨论】:

    • 谢谢,这对我有帮助。不幸的是,我需要在包含“foo”的数组中放入一些东西。那么我该如何写入呢?
    【解决方案2】:

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

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

    【讨论】:

    • OP 想要改变它的值。
    【解决方案3】:

    [编辑:我试图变得太可爱,它咬了我。最初我建议使用array.to_s[/\[+/].size 来确定级别数的两种方法。其中一种方法使用eval 将字符串转换为输出数组。 @FrederickCheung 指出了您可以在 cmets 中看到的两个缺陷(感谢 Frederick)。如果您想查看我的原始答案,当然可以查看编辑。我现在已经编辑建议我最初提出的第一种方法的更传统的变体。

    这是一个非递归方法。

    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"}]]]]]
    

    【讨论】:

    • 如果值是包含[ 的内容,则数组 to_s 版本在转换为字符串时会产生不正确的结果
    • 只有当to_s 的输出是用于创建该类型对象的 ruby​​ 语法时,基于 eval 的替换方法才有效(因此 replace_foo(array, "exit")) 不起作用)
    • 哦,该死,但是谢谢@FrederickCheung。我了解eval 问题,但不是您的第一条评论。能举个例子吗?
    • 例如array = [[[["foo[]"]]]]
    • 其实这是错误的——inspect 的输出必须以 [
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2019-03-04
    相关资源
    最近更新 更多