2014-03-02 122 views
0

我很困惑这个代码对我不起作用。理解红宝石注入

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

+3

这整个事情可以写'tab.join(“‘)分裂(’”)' –

+0

@MarkThomas为你的想法+1。 :-) –

回答

1

在您的#inject块中,您通过了最后一个条目"5,6"。现在在if块内,将其分割为一个数组。然后你在[5,6]上调用方法#each。现在#each方法返回您调用它的接收器。

但在第二种情况下,您在inject块的每次迭代的最后一次调用t.each。所以最终通过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"] 
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] 
}