Question

I'm confused about this codethat didn't work for me.

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 but if i change the code,

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

======output: 1 2 3 4 5 6 does anyone has an explanation? thx

Was it helpful?

Solution

In your #inject block, you passed last entry as "5,6". Now inside the if block, you splitted it to an array. Then you called the method #each on [5,6]. Now #each method returns the receiver on which you called it.

But in the second case, you called t.each at the last of each iteration of the inject block. So on the final pass t is a complete array [1,2,3,4,5,6]. Now as I said, Array#each returns the receiver, so you got the full t back , that [1,2,3,4,5,6].

I would write your code as :

ary = ["1,2,3","4","5,6"]
ary.flat_map { |str| str.include?(",") ? str.split(',') : str }
# => ["1", "2", "3", "4", "5", "6"]

If you want to use #inject do :

ary = ["1,2,3","4","5,6"]
ary.inject([]) { |a,str| a.concat(str.split(',')) }
# => ["1", "2", "3", "4", "5", "6"]

OTHER TIPS

With inject, the return value from each block is passed to the subsequent block. Your first example, the return value is the value of s.each{|y| t<<y}; the final iteration will return [5, 6]. Your second example indirectly returns t; t.each { } returns t so that additional methods can be chained to it.

You need to return the collection you're building up at the end of each block:

x=tab.inject([]){|t,elt|

  if elt.include?(',')
    s=elt.split(',')
    s.each{|y| t << y}
  else
    t<<elt
  end

  t

}

You can make this significantly smaller however; just add the new element(s) to the existing elements, and return the result:

tab.inject([]) { |t, elt|
  t + elt.include?(',') ? elt.split(',') : Array[elt]
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top