【问题标题】:How to reimplement the map method in ruby using recursion?如何使用递归在 ruby​​ 中重新实现 map 方法?
【发布时间】:2015-05-06 02:02:40
【问题描述】:

我是一名 ruby​​ 新手,正在学习编码。我想了解Enumerable 模块提供的一些方法是如何工作的。所以我正在重新实现它们。一个挑战是使用递归来实现它们。但是,我在尝试使用递归实现 Enumerable#Map 方法时遇到了问题。

这是我的代码:

class Array
  def mymap_recursive(&block)
    copy_of_array = dup
    new_array = []
    return new_array if copy_of_array.empty?
    value = copy_of_array.shift
    new_array << yield(value)
    copy_of_array.mymap_recursive(&block)
  end
end

我试图弄清楚为什么它不起作用,所以我放了

puts "#{new_array}"

在方法结束时。然后在 Sublime Text 中,我做到了

arr = [2,2,5,5,10]
arr.mymap_recursive {|n| n * n}

按cmd+b后,我得到的输出是:

[100]
[25]
[25]
[4]
[4]

我不明白为什么它没有返回一个包含所有值的数组。

感谢您的帮助!

【问题讨论】:

  • 如果数组副本为空,则在第 3 行返回 new_array(即 [])。你把它和其他东西放在哪里?
  • 对我来说,第 3 行代表基本情况,如果条件为真,递归应该中断。我以为它只会返回一个包含所有值的 new_array。
  • 是的,这是基本情况......它只会返回 new_array 没有任何内容......因为这就是你将 [] 分配给它之后它所拥有的......;)您还必须有一个案例,其中包含 something 的 new_array

标签: ruby recursion


【解决方案1】:

您的代码中发生的情况是,每次您调用 mymap_recursive(&amp;block) 时,new_array 都会丢失。要解决这个问题,您必须有一种方法来维护正在递归构建的新数组。对代码的一个简单更改是在方法定义中包含new_array = [],然后每次都传递新数组。这是我的更改的代码:

class Array
  def mymap_recursive(new_array = [], &block)
    copy_of_array = self.dup
    return new_array if copy_of_array.empty?
    value = copy_of_array.shift
    new_array << yield(value)
    copy_of_array.mymap_recursive(new_array, &block)
  end
end

然后当你打电话时

arr = [2,2,5,5,10]
p arr.mymap_recursive {|n| n * n}
#returns
#[4, 4, 25, 25, 100]

如果您对此语法有任何疑问或有任何问题,请告诉我,我会尽力解释!

【讨论】:

    【解决方案2】:

    另一个不改变方法签名并且不改变任何数据的解决方案:

    class Array
      def mymap_recursive(&block)
        if empty?
          []
        else
          [block.call(first)] + drop(1).mymap_recursive(&block)
        end
      end
    end
    

    【讨论】:

    • 非常感谢您的帮助!不过,我对这个方法有一个疑问:第 6 行不是从调用 mymap 方法的原始数组中删除一个元素吗?
    • 是的。但它也会在加号之前处理删除的元素。第 6 行执行两个任务,用加号分隔。在加号之前,它采用数组的“第一个”元素并在其上调用块(在您的示例中为“n * n”)。在加号之后,它删除第一个元素(已经平方的那个),并将这个方法应用于所有剩余的元素。然后,+ 运算符加入双方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    • 2017-04-23
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-27
    相关资源
    最近更新 更多