编写Ruby注入方法?

时间:2018-04-20 21:06:35

标签: ruby

我有点困惑为什么这个答案是"错误"基于Ruby自己对" Inject"的解释。方法(对于这种情况下的数组,我正在做" Odin项目"用于学习任务的项目)

def my_inject(start = nil)
  memo = self[0] if start.nil?
  for i in 0...self.length do
    puts "#{memo}:#{self[i]} Results=#{yield(memo,self[i])}"
    memo = yield(memo,self[i])
  end
  return memo
end



[5,6,7,8,9,10].my_inject { |sum, n| sum + n } 

以上具体回复:

5:5 Results=10
10:6 Results=16
16:7 Results=23
23:8 Results=31
31:9 Results=40
40:10 Results=50
=> 50

哪个有道理?如果未定义起始值,则使用第一个值。但是根据Ruby的API文档:"Inject"它应该是45 ....

这对我没有意义。我们从第一个值的备忘录开始,并将其添加到"元素"值。这是10(在这种情况下)......等等。或者他们在你没有指定价值时说?你应该跳过第一个数组值吗?

我的意思是如果我加上5 + 6 + 7 + 8 + 9 + 10是的,这是正确的45,但如果我正在做阻止我要做的事情,我觉得" 50"更有意义吗?虽然显然我错了,我只是不确定在哪里。

我的意思是如果我们没有给出一个起始值,我可以确定我可以在1处开始索引......但这看起来很奇怪。

由于

1 个答案:

答案 0 :(得分:3)

正如人们在评论中指出的那样,如果没有提供参数,你的解决方案会双击第一个元素。

这是一个非常简单的实现,删除了您的解决方案中包含的一些不必要的元素,并且不仅适用于数组:

module Enumerable
  def my_inject(memo = nil)
    each { |x| memo = memo.nil? ? x : yield(memo, x) }
    memo
  end
end

p (1..5).my_inject(&:*)                               # 5 factorial  =>  120
p (1..5).my_inject(2, &:*)                            # 5 factorial doubled => 240
p %w(3 4 5).my_inject(&:+)                            # string concatenation => "345"
p %w(3 4 5).my_inject("hello", &:+)                   # concatenation w/ prefix => "hello345"
p %w(3 4 5).my_inject("howdy") { |memo, x| memo + x } # prefix and block => "howdy345"

<强>附录

如果您想进一步处理SymbolString Enumerable#inject参数,您需要进行一些预处理以确定您要处理的内容:

module Enumerable
  def my_inject(memo = nil, sym = nil, &block)
    memo = memo.to_sym if memo.is_a?(String) && !sym && !block
    block, memo = memo.to_proc, nil if memo.is_a?(Symbol) && !sym
    sym = sym.to_sym if sym.is_a?(String)
    block = sym.to_proc if sym.is_a?(Symbol)

    # Ready to rock & roll
    each { |x| memo = memo.nil? ? x : block.yield(memo, x) }
    memo
  end
end

# A variety of test cases    
p (1..4).my_inject(:*)                                # 4 factorial via Symbol =>  24
p (1..5).my_inject('*')                               # 5 factorial via String =>  120
p (1..6).my_inject { |memo, x| memo * x }             # 6 factorial via block => 720
p (1..5).my_inject(2, &:*)                            # 5 factorial doubled via Proc => 240
p (1..5).my_inject(3, :*)                             # 5 factorial tripled via Symbol =>  360
p (1..5).my_inject(4, '*')                            # 5 factorial quadrupled via String =>  480
p %w(3 4 5).my_inject(&:+)                            # string concatenation via Proc => "345"
p %w(3 4 5).my_inject("hello", &:+)                   # prefix and Proc => "hello345"
p %w(3 4 5).my_inject("howdy") { |memo, x| memo + x } # prefix and block => "howdy345"
p %w(3 4 5).my_inject("yowza", :+)                    # prefix and Symbol => "yowza345"
p %w(3 4 5).my_inject("yoiks", '+')                   # prefix and String => "yoiks345"