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

问题描述 投票:2回答:2

对编码很新,并且经历过Ruby中一些比较常用的方法,猴子修补它们以便更好地理解每个方法的工作方式(btw有多大帮助)。

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

我正在为#inject类创建自己的Array方法,我想以递归方式编写它。该方法将允许传递可选的累加器,以及proc。如何使用以下格式完成此操作?

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

另外,如果我使用#dup,我是否需要担心改变原始数组?感谢您的帮助!

arrays ruby inject proc accumulator
2个回答
4
投票

另一种实现方式

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

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

至于你是否应该担心改变原文 - 简而言之 - 是的。通常,Ruby中的方法不会在可能的情况下改变对象并进行复制。经常有爆炸(!)替代品。所述“危险”方法使原件变异而不是返回副本。但是,在这种情况下,这是没有意义的。原始是一个数组,结果是总和。

至于改变原文并单独返回结果,除非你有真正的表现(或其他)考虑,否则你不应该这样做。它不直观,可能导致混乱的情况。


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  
© www.soinside.com 2019 - 2024. All rights reserved.