我正在使用这种注入方法将一组运行的值组合成一个数组。我想弄清楚为什么我会收到错误。
def running_totals(myarray)
results = []
myarray.inject([]) do |sum,n|
results << sum + n
end
results
end
p running_totals([1,2,3,4,5])
我收到错误
in `+': no implicit conversion of Fixnum into Array (TypeError)
当打破这个方法时,这不是添加两个整数并将其添加到数组中吗?我在这里有点困惑。谢谢你的帮助。
答案 0 :(得分:3)
在第一次迭代中,sum
将是一个数组(正如您在调用inject([])
时将数组指定为默认值),并尝试向其中添加数字。在results << sum + n
声明中
相反,将初始值设置为0
,然后添加,然后将结果添加到数组中,然后确保让sum
传递到下一次注入迭代。
def running_totals(myarray)
results = []
myarray.inject(0) do |sum,n| # First iteration sum will be 0.
sum += n # Add value to sum.
results << sum # Push to the result array.
sum # Make sure sum is passed to next iteration.
end
results
end
p running_totals([1,2,3,4,5]) #=> [1, 3, 6, 10, 15]
答案 1 :(得分:2)
results << sum + n
的结果是一个数组results
,而这就是取代sum
值,因此您尝试将fixnum n
添加到下一次迭代中一个数组sum
...加上你将sum
的值初始化为数组没有帮助。
确保注入块中最后执行的语句是您想要的累计值。
def running_totals(myarray)
results = []
results << myarray.inject do |sum, n|
results << sum
sum + n
end
results
end
p running_totals([1,2,3,4,5])
=> [1, 3, 6, 10, 15]
请注意,我也将inject的结果移动到results数组中,因此也包含了最终值,否则你只有四个值并且会丢失final(15)值。
答案 2 :(得分:1)
inject
块的返回值在下次调用块时作为第一个参数传递,因此必须匹配。在您的代码中,您将数组作为初始值传递,然后返回一个数组;到现在为止还挺好。但是在代码块中,您将该数组参数(sum
)视为一个数字,但不会起作用。试试这个:
def running_totals(myarray)
myarray.inject([]) do |results,n|
results << n + (results.last || 0)
end
end
作为[]
的参数传递的inject
成为results
的第一个值;第一个数组元素(示例中为1
)成为n
的第一个值。由于results
为空,results.last
为nil
,(results.last || 0)
的结果为0
,我们将其添加到n
以获得1,我们推入results
,然后从块中返回新修改的数组值。
第二次进入该区块时,results
是我们刚刚从第一次传递返回的数组[1]
,而n
是2
。这一次results.last
为1
而不是nil
,因此我们将1
添加到2
以获取3
并将其推送到数组,然后返回[1,3]
。
第三次进入该区块时,results
为[1,3]
,n
为3
,因此返回[1,3,6]
。等等。
答案 3 :(得分:0)
根据ri,你必须从inject的块中返回计算结果。
From: enum.c (C Method):
Owner: Enumerable
Visibility: public
Signature: inject(*arg1)
Number of lines: 31
Combines all elements of enum by applying a binary
operation, specified by a block or a symbol that names a
method or operator.
If you specify a block, then for each element in enum
the block is passed an accumulator value (memo) and the element.
If you specify a symbol instead, then each element in the collection
will be passed to the named method of memo.
In either case, the result becomes the new value for memo.
At the end of the iteration, the final value of memo is the
return value for the method.
If you do not explicitly specify an initial value for memo,
then uses the first element of collection is used as the initial value
of memo.
Examples:
# Sum some numbers
(5..10).reduce(:+) #=> 45
# Same using a block and inject
(5..10).inject {|sum, n| sum + n } #=> 45
# Multiply some numbers
(5..10).reduce(1, :*) #=> 151200
# Same using a block
(5..10).inject(1) {|product, n| product * n } #=> 151200
# find the longest word
longest = %w{ cat sheep bear }.inject do |memo,word|
memo.length > word.length ? memo : word
end
longest
因此,如果您为每次迭代返回计算结果,那么您的样本将起作用,如下所示:
def running_totals(myarray)
results = []
myarray.inject do |sum,n|
results << sum + n
results.last # return computation result back to Array's inject
end
results
end
希望它有所帮助。