如何使用递归重新实现ruby中的map方法?

时间:2015-05-06 02:02:40

标签: ruby recursion

我是一个红宝石新手,学习编码。我想了解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]

我无法弄清楚为什么它没有返回一个包含所有值的数组。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

每次拨打mymap_recursive(&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]

如果您对此语法有任何疑问或有任何问题请与我联系,我会尽力解释一下!

答案 1 :(得分:1)

另一种解决方案,它不会改变方法签名并且不会改变任何数据:

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