使用递归重写Ruby #inject(#reduce)?

时间:2018-06-25 06:27:13

标签: arrays ruby inject proc accumulator

编码的新手,并通过了Ruby中一些更常用的方法,对它们进行了猴子修补,以更好地了解每种方法的工作方式(顺便说一句,它为我们提供了大量帮助)。

现在我再次做同样的事情,但是对于以前迭代的那些人,我正在使用递归。我的问题是:

我正在为#inject类创建自己的Array方法,并且我想递归地编写它。该方法将允许传递可选的累加器以及proc。使用以下格式该怎么做?

class Array
  def my_inject(accum = nil, &prc)
    #code
  end 
end

此外,我是否需要担心会改变原始数组,我应该使用#dup吗?感谢您的提前帮助!

2 个答案:

答案 0 :(得分:4)

替代实现

class Array
  def aggregate(accumulator = nil, &sumator)
    return accumulator if empty?

    drop(1).aggregate(accumulator ? sumator.(accumulator, first) : first, &sumator)
  end
end

至于您是否需要担心对原件的修改-简而言之-是的。通常,Ruby中的方法在可能的情况下不会变异对象并进行复制。经常有很多(!)替代方法。所说的“危险” 方法会在原位置进行变异,而不是返回副本。但是,在这种情况下,这没有任何意义。原来是一个数组,结果是总和。

对于变异原始文件并分别返回结果,除非您有实际的性能(或其他方面)考虑,否则不应该这样做。这是不直观的,并且可能导致混乱的情况。

答案 1 :(得分:0)

我想我明白了!

class Array
  def my_inject(acc=nil, &prc)  
    return acc if empty?    
    acc = self.shift if acc.nil? 

    acc = prc.call(acc, self.first)    
    self.shift    
    my_inject(acc, &prc)    
  end    
end  

我唯一的问题是,这是否有问题/它会改变原始数组吗?

编辑:添加了不会变异原始版本的版本。

class Array
  def my_inject(acc=nil, &prc)  
    new_arr = self.dup
    return acc if empty?    
    acc = new_arr.shift if acc.nil? 

    acc = prc.call(acc, self.first)    
    new_arr.shift    
    my_inject(acc, &prc)    
  end    
end