我有代码:
class Scene
def initialize(number)
@number = number
end
attr_reader :number
end
scenes = [Scene.new("one"), Scene.new("one"), Scene.new("two"), Scene.new("one")]
groups = scenes.inject({}) do |new_hash, scene|
new_hash[scene.number] = [] if new_hash[scene.number].nil?
new_hash[scene.number] << scene
end
Run Code Online (Sandbox Code Playgroud)
当我发起它时,我得到错误:
freq.rb:11:in `[]': can't convert String into Integer (TypeError)
from freq.rb:11:in `block in <main>'
from freq.rb:10:in `each'
from freq.rb:10:in `inject'
from freq.rb:10:in `<main>'
Run Code Online (Sandbox Code Playgroud)
如果我将场景更改为:
scenes = [Scene.new(1), Scene.new(1), Scene.new(2), Scene.new(1)]
Run Code Online (Sandbox Code Playgroud)
问题消失了.
为什么我在第一种情况下收到错误消息?为什么Ruby决定将scene.number从String转换为Integer?
还有一个关于'注入'方法的问题.当Ruby初始化'new_hash'变量时,Ruby如何知道这个变量的类型?
the*_*Man 10
尝试:
groups = scenes.inject({}) do |new_hash, scene|
new_hash[scene.number] = [] if new_hash[scene.number].nil?
new_hash[scene.number] << scene
new_hash
end
Ruby将传递给inject()的空哈希值设置为new_hash.当块结束时,返回值用于在下一次通过时初始化new_hash,即new_hash继续累积块的结果.
在您的原始代码中,您没有返回散列但是数组(new_hash [scene.number]是一个数组)并且下一个循环通过Ruby抱怨,因为new_hash [scene.number]试图用字符串查找数组价值,因此你得到的错误.
小智 6
ZED是对的.参见Jay Fields的思考:Ruby:inject通过例子注入一个很好的解释.
如图所示,您的块返回一个数组.所以new_hashin |new_hash, scene|最终成为那个数组.当Ruby尝试查找数组索引'one'时,它会抛出错误,因为'one'是String而不是Integer.
所有你需要做的就是返回new_hashZED显示,你会得到这样的东西:
{
"two" => [
#<Scene:0x101836470 @number="two">
],
"one" => [
#<Scene:0x101836510 @number="one">,
#<Scene:0x1018364c0 @number="one">,
#<Scene:0x101836420 @number="one">
]
}
Run Code Online (Sandbox Code Playgroud)