Ruby 如何创建inject方法的自定义实现?
开始看起来很容易。以下是我在几分钟内编写的第一个代码块:Ruby 如何创建inject方法的自定义实现?,ruby,Ruby,开始看起来很容易。以下是我在几分钟内编写的第一个代码块: module Enumerable def my_inject(memo=false) memo = memo ? memo : self[0] self.my_each do |item| memo = yield(memo, item) end return memo end end 当使用初始值调用inject方法时,它会按预期工作。但是我还没有找到一种方法,使它在没有任何初
module Enumerable
def my_inject(memo=false)
memo = memo ? memo : self[0]
self.my_each do |item|
memo = yield(memo, item)
end
return memo
end
end
当使用初始值调用inject方法时,它会按预期工作。但是我还没有找到一种方法,使它在没有任何初始值的情况下正常工作
例如:
puts [1,2,3,4].my_inject(0) { |memo, i| memo+i} #=> 10
puts [1,2,3,4].my_inject { |memo, i| memo+i} #=> 11
这就是原始Ruby inject方法的输出:
puts [1,2,3,4].inject { |memo, i| memo+i} #=> 10
Ruby医生说
如果未明确指定备注的初始值,则
集合的第一个元素用作备注的初始值
那么如何为初始值设置合适的数据类型呢?我们应该为Ruby中的每种数据类型设置一个条件,并为每种数据类型设置一个默认值吗
那么如何为初始值设置合适的数据类型呢?我们应该为Ruby中的每种数据类型设置一个条件,并为每种数据类型设置一个默认值吗
否,默认值是集合的第一个元素
Ruby允许您定义自己的类,因此为每种可能的类型编写一个案例是不可能的,因为它们的数量是无限的。如果调试Ruby自己的实现,您将看到它在没有给出默认备注的情况下从第二个元素开始迭代:
> [1,2,3].inject { |m, i| puts "M: #{m} | I: #{i}"; break }
M: 1 | I: 2
因此,您的实现应该如下所示:
def my_inject(*args)
init = args.size > 0
memo = init ? args[0] : self[0]
self.drop(init ? 0 : 1).my_each do |item|
memo = yield(memo, item)
end
return memo
end
puts [1,2,3,4].my_inject(0) { |memo, i| memo+i} #=> 10
puts [1,2,3,4].my_inject { |memo, i| memo+i} #=> 10
之所以使用
init=args.size>0
是因为您必须考虑到有人可能想要执行[…].my_inject(false){…}
。因此,您无法检查memo==false
要确定是否需要跳过第一个元素,您必须检查给出的实际参数计数。只是出于好奇:
class Array
def my_inject(memo = nil, enum = self.each)
return enum_for(:my_inject) unless block_given?
memo = enum.next if memo.nil?
my_inject(yield(memo, enum.next), enum, &Proc.new)
rescue StopIteration
memo
end
end
[1,2,3].my_inject(3) { |memo, v| memo += v }
#⇒ 9
[1,2,3].my_inject &:*
#⇒ 6
谢谢你的回答和解释“假”案例。你说得对。