【问题标题】:Ruby: Standard recursion patternsRuby:标准递归模式
【发布时间】:2012-05-21 07:25:34
【问题描述】:

我经常在 ruby​​ 中迷上的一件事是递归模式。例如,假设我有一个数组,它可能包含数组作为无限深度的元素。所以,例如:

my_array = [1, [2, 3, [4, 5, [6, 7]]]]

我想创建一个可以将数组展平为[1, 2, 3, 4, 5, 6, 7] 的方法。

我知道 .flatten 可以完成这项工作,但这个问题是我经常遇到的递归问题的一个示例 - 因此我正在尝试找到一个更可重用的解决方案。

简而言之 - 我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏

【问题讨论】:

    标签: ruby recursion design-patterns


    【解决方案1】:

    递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情况(递归情况)和破坏它的情况(基本情况)。例如,在 Ruby 中进行递归展平:

    class Array
      def deep_flatten
        flat_map do |item|
          if item.is_a?(Array)
            item.deep_flatten
          else
            [item]
          end
        end
      end
    end 
    
    [[[1]], [2, 3], [4, 5, [[6]], 7]].deep_flatten
    #=> [1, 2, 3, 4, 5, 6, 7]
    

    这有帮助吗?无论如何,这里显示的一个有用模式是,当您在数组上使用 recusion 时,您通常需要flat_mapeach + concat/push 的功能替代品)。

    【讨论】:

    • 感谢您的回复。我最初尝试使用类之外的函数,该函数不会递归调用 item.my_flatten ......但这有效。干杯
    • @PlankTon。将 my_flatten 编写为函数只需要对上面的代码进行一些小的更改。但是作为一种 OOP 语言,my_flatten 是一种通用算法,将其添加到 Array 中是有意义的。
    【解决方案2】:

    好吧,如果你懂一点 C ,你只需要访问文档并单击 ruby​​ 函数来获取 C 源代码,它就在那里..

    http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-flatten
    

    对于这种情况,这是一个 Ruby 实现

    def flatten values, level=-1
      flat = []
      values.each do |value|
        if level != 0 && value.kind_of?(Array)
          flat.concat(flatten(value, level-1))
        else
          flat << value
        end
      end
      flat
    end
    
    p flatten [1, [2, 3, [4, 5, [6, 7]]]] 
    #=> [1, 2, 3, 4, 5, 6, 7] 
    

    【讨论】:

    • 啊-连续。我试图递归调用函数本身,但这会做到。干杯
    【解决方案3】:

    这是一个以尾递归样式编写的展平示例。

    class Array
    
      # Monkeypatching the flatten class
      def flatten(new_arr = [])
        self.each do |el|
          if el.is_a?(Array)
            el.flatten(new_arr)
          else
            new_arr << el
          end
        end
    
        new_arr
      end
    end
    
    p flatten [1, [2, 3, [4, 5, [6, 7]]]] 
    #=> [1, 2, 3, 4, 5, 6, 7]
    

    虽然看起来 ruby​​ 并不总是针对尾递归进行优化:Does ruby perform tail call optimization?

    【讨论】:

      猜你喜欢
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 2014-01-12
      • 2012-06-13
      相关资源
      最近更新 更多