【问题标题】:Rewriting Ruby #inject (#reduce) using recursion?使用递归重写 Ruby #inject (#reduce)?
【发布时间】:2018-12-03 16:09:37
【问题描述】:

刚接触编码,并且已经了解了 Ruby 中一些更常用的方法,猴子修补它们以更好地了解每种方法的工作原理(顺便说一句,这帮助了很多)。

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

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

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

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

【问题讨论】:

  • 你想在my_inject里面写什么?
  • 不知道你是不是在开玩笑,但如果不是,我想为 Array 类编写一个与 Ruby 的 Enumerable #inject (#reduce) 方法相同的方法,如原帖所述
  • ^ 使用递归

标签: arrays ruby inject proc accumulator


【解决方案1】:

我想我明白了!

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  

【讨论】:

  • 谢谢@ndn,我添加了一个没有的版本。虽然,我不确定这是否是最好的方法
【解决方案2】:

另一种实现

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

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

至于您是否应该担心改变原版 - 简而言之 - 是的。如果可能,Ruby 中的方法通常不会改变对象并制作副本。经常有 bang (!) 替代方案可以做到。所说的 “危险” 方法会在原地改变原件,而不是返回副本。但是,在这种情况下,这是没有意义的。原来是一个数组,结果是和。

至于变异原始并分别返回结果,除非您有真正的性能(或其他)考虑,否则您不应该这样做。这是不直观的,可能会导致混乱的情况。

【讨论】:

  • hmm,为我返回 nil。我尝试使用 array = [1, 2, 3] , prc = Proc.new {|x,y| x + y},有和没有累加器
  • @Zezuz 再试一次,我原来的版本有一个小错误。
  • 工作,谢谢!我喜欢你使用#drop,而不是像使用#dup 那样创建不同的数组。 (因为 drop 不会变异)
  • 也可以这样做,因此您不必编写“array.method”,因为 self 不是必需的。抱歉,我不能投票,因为我仍然是新手。如果可以的话:(
  • @Zezuz,很高兴它有帮助。
猜你喜欢
  • 1970-01-01
  • 2019-05-21
  • 2013-04-03
  • 1970-01-01
  • 2018-06-24
  • 2022-01-16
  • 2012-12-03
  • 2021-10-24
  • 2020-03-01
相关资源
最近更新 更多