我对这个对我不起作用的代码感到困惑。
tab=Array.new
tab<<"1,2,3"
tab<<"4"
tab<<"5,6"
x=tab.inject([]){|t,elt|
if elt.include?(',')
s=elt.split(',')
s.each{|y| t<<y}
else
t<<elt
end
}
STDOUT.puts x
============= outpout:5 6 但如果我改变代码,
tab=Array.new
tab<<"1,2,3"
tab<<"4"
tab<<"5,6"
x=tab.inject([]){|t,elt|
if elt.include?(',')
s=elt.split(',')
s.each{|y| t<<y}
else
t<<elt
end
t.each{|tt| tt} #i add this line
}
STDOUT.puts x
======输出:1 2 3 4 5 6 有人有解释吗? THX
答案 0 :(得分:1)
在#inject
区块中,您将最后一个条目作为"5,6"
传递。现在在if
块内,您将其拆分为数组。然后,您在#each
上调用了方法[5,6]
。现在#each
方法返回您调用它的接收器。
但在第二种情况下,您在t.each
块的每次迭代的最后一次调用inject
。因此,在最后一次传递t
上是一个完整的数组[1,2,3,4,5,6]
。现在正如我所说,Array#each
返回接收者,因此你得到了t
的完整[1,2,3,4,5,6]
。
我会把你的代码写成:
ary = ["1,2,3","4","5,6"]
ary.flat_map { |str| str.include?(",") ? str.split(',') : str }
# => ["1", "2", "3", "4", "5", "6"]
如果您想使用#inject
,请执行:
ary = ["1,2,3","4","5,6"]
ary.inject([]) { |a,str| a.concat(str.split(',')) }
# => ["1", "2", "3", "4", "5", "6"]
答案 1 :(得分:0)
使用inject
,每个块的返回值将传递给后续块。第一个例子,返回值是s.each{|y| t<<y}
的值;最后的迭代将返回[5, 6]
。你的第二个例子间接返回t
; t.each { }
返回t
,以便可以将其他方法链接到其中。
您需要返回每个块末尾正在构建的集合:
x=tab.inject([]){|t,elt|
if elt.include?(',')
s=elt.split(',')
s.each{|y| t << y}
else
t<<elt
end
t
}
然而,你可以使这个显着缩小;只需将新元素添加到现有元素,然后返回结果:
tab.inject([]) { |t, elt|
t + elt.include?(',') ? elt.split(',') : Array[elt]
}