我正在编写一种计算数字阶乘的方法,我在搜索中发现了类似的东西。
def factorial(number)
(1..number).inject(:*) || 1
end
它有效并且我理解注入函数正在做什么,但我不清楚(:\*)
部分真正意味着什么。
我知道它必须是写{|num, prod| num*prod}
的速记版本,但我希望有一个明确的解释。谢谢!
答案 0 :(得分:2)
:*
只是*
执行方法inject
的方法名称。如果您查看inject
http://ruby-doc.org/core-2.2.2/Enumerable.html#method-i-inject
它声明
如果指定了符号,则集合中的每个元素都将传递给命名的备忘录方法。在任何一种情况下,结果都将成为备忘录的新值。在迭代结束时,memo的最终值是方法的返回值。
因此inject { |memo, obj| block }
以下是相同的
ary = [1,2,3]
ary.inject(:*)
#=> 6
ary.inject { |memo, obj| memo.*(obj) }
#=> 6
答案 1 :(得分:2)
:*
是一个符号。符号是不可变的字符串。 :*
与"*"
类似,只是它不可变。
在ruby中,乘法也是一种方法调用。它相当于调用第一个乘数的.*(second)
方法,第二个乘数作为参数。实际上,您可以输入3.*(4)
而不是3*4
。就红宝石而言,3*4
只是语法糖。
可以通过public_send
符号消息调用对象来调用ruby中的方法调用。 3.public_send(:*, 4)
也可以像3*4
一样工作。
inject的参数被解释为应该是什么类型的消息public_senT
,也就是说,应该从inject方法的内部调用什么方法。
你可以想到
[ 1, 2, 3, 4 ].inject(:*)
注射' *'在inject
上调用的每个可枚举对象的每个相邻对之间:
[ 1, 2, 3, 4 ].inject(:*) == 1 * 2 * 3 * 4
当然1 * 2 * 3 * 4
相当于从左到右,并在您的正在运行的计数上应用:*以及下一个数字以获得下一个计数,然后返回最终结果。
module Enumerable
def inject_asterisk
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = tally * next_num
end
return tally
end
end
[2, 3, 5].inject_asterisk #=> 30
您可以通过组合tally
和next_number
的操作来概括这一点,以获得您的下一个tally
参数函数。 ruby中的块基本上用作始终具有保留点的参数函数。
module Enumerable
def inject_block(&block)
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = block.call(tally, next_num)
end
return tally
end
end
[2, 3, 5].inject_block {|tally, next_num| tally + next_num } #=> 10
如果您的区块总是具有
形式{|tally, next_num| tally.method_of_tally(next_num) }
就像这种情况一样(记住tally + next_num
< ==> tally.+(next_num)
< ==> tally.public_send(:+,next_num)
,您可以决定只传递:method_of_tally
作为论据并暗示阻止。
module Enumerable
def my_inject(method_of_tally_symbol, &block)
if method_of_tally_symbol
block = Proc.new { |tally, next_num|
tally.public_send(method_of_tally_symbol, next_num)
}
end
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = block.call(tally, next_num)
end
return tally
end
end
[2, 3, 5].my_inject(:+) #=> 10
将重复的模式提取到可重用的组件中是为了让您不必输入任何内容。
答案 2 :(得分:0)
这意味着array.map { |e| e.join }
,这是一个捷径。通常你会写一些类似
array.map(&:join)
用符号表示proc,速记就是
inject
reduce
和&
相似,但在这些情况下您不需要numbers
例如,如果您有一组名为numbers.inject(&:+)
要对数字求和,您可以
numbers.inject(:+)
或者你可以不用&符号
OrderedDict
答案 3 :(得分:0)
http://ruby-doc.org/core-2.2.2/Enumerable.html#method-i-inject
Inject是一个枚举方法,它使用符号(如您的情况)或块(如您提议的缩写)组合所述枚举的元素。
例如:
sort
相当于(5..10).reduce(:*)