2016-07-04 98 views
-2

请帮助我理解迭代在String实例和自定义类实例之间的区别。Ruby在遍历自定义类实例时返回实例

a = ["pew", "pie"] 
a.inject do |memo, instance| 
    memo + instance 
end 

它工作正常。按预期返回“pewpie”。

class Boom 
    def slash 
    3 
    end 

    def ping 
    5 
    end 
end 

a = [Boom.new] 
a.inject do |memo, instance| 
    memo + instance.slash + instance.ping 
end 

这出于某种原因返回实例本身 - 繁荣:0x00000005018a38

+0

只有1元件'Boom.new'在阵列。因此它不会遍历... –

回答

3

关键的一点是这个音符inject文档中: 如果你不明确指定备忘录的初始值,则第一集合的元素被用作备忘录的初始值。

在你的情况,你应该这样做

a.inject(0) { |memo, instance| memo + instance.slash + instance.ping } 
# 8 

否则你用型臂,备忘录的对象的引用。

+0

你是对的。谢谢。 – fieryvova

2

当没有累加器的初始值时,使用第一个元素。如果有只有一个数组元素的 - 块将不会运行:

[1].inject{ raise "Boom!" } 
# => 1 
[1].inject(0){ raise "Boom!" } 
# => RuntimeError: Boom! 

所以,你需要或者提供初始值的重新定义+运营商类。

+0

谢谢。你是对的。 – fieryvova

1

这里有两种解决方案:

a = [Boom.new, Boom.new, Boom.new] 
# => [#<Boom:0x007ffaf90a9c08>, #<Boom:0x007ffaf90a9be0>, #<Boom:0x007ffaf90a9bb8>] 

# 1) memo is a String 
a.inject('') {|memo, instance| memo + instance.slash.to_s + instance.ping.to_s} 
# => "353535" 

# 2) memo is an Array 
a.inject([]) {|memo, instance| memo << instance.slash.to_s + instance.ping.to_s} 
# => ["35", "35", "35"] 

见:http://ruby-doc.org/core-2.3.1/Enumerable.html#method-i-inject

+1

谢谢!我的错。我应该更加注意地阅读文档。 – fieryvova