Break from select

Hi,

I have an array like a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]
I need to select elements which are divisible by 2 and select only

5 elements.

col = a.select do |e|
  e %2 == 0
end

I get all the elements into col which are divisible by 2 and working

fine.

what if I want to select only 5 elements
I am trying below code
i = 0
 col = a.select do |e|
  i += 1
  break if i > 5
  e %2 == 0
end

Now col returns nil.
Also used return but getting error.

Any solution for this.

Thanks,
Venkat

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
a = a.select { |x| x%2 == 0 }
a = a.slice(0,5)
puts “#{a.inspect}”

Is this what you are expecting?

On Fri, Mar 25, 2011 at 12:35 PM, Venkat S.
<[email protected]

Hi Venkat,

Quick Solution,
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
b =[]
a.collect{|x| b << x if x %2 == 0 and b.length<5}
puts b.inspect

Cheers,
Sarav

Venkat S. wrote in post #989134:

Hi,

I have an array like a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]
I need to select elements which are divisible by 2 and select only

5 elements.

col = a.select do |e|
  e %2 == 0
end

I get all the elements into col which are divisible by 2 and working

fine.

what if I want to select only 5 elements
I am trying below code
i = 0
 col = a.select do |e|
  i += 1
  break if i > 5
  e %2 == 0
end

Now col returns nil.
Also used return but getting error.

Any solution for this.

Thanks,
Venkat

Thanks Saravanan for your reply. I thought of doing this .
But the problem is array size. Here I defined array with 15 elements.
What if we have 1000 of elements in array.

Below code a.collect will iterate for all the elements even if I
achieved 5 elements.

Saravanan K. wrote in post #989140:

Hi Venkat,

Quick Solution,
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
b =[]
a.collect{|x| b << x if x %2 == 0 and b.length<5}
puts b.inspect

Cheers,
Sarav

On Fri, Mar 25, 2011 at 8:37 AM, Saravanan K.
[email protected] wrote:

puts b

You are still iterating the whole input Array. This is better

irb(main):001:0> a = 1.upto(15).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
irb(main):002:0> b = []
=> []
irb(main):003:0> a.each {|x| if x % 2 == 0; b << x; break if b.size >= 5
end}
=> nil
irb(main):004:0> b
=> [2, 4, 6, 8, 10]

Insert “p x” at beginning of block to see that we really short circuit.

If you want to get fancy you can do this as well:

irb(main):010:0> b = []
=> []
irb(main):011:0> a.each {|x| p x; x % 2 == 0 and b << x and b.size >=
5 and break}
1
2
3
4
5
6
7
8
9
10
=> nil

We can even integrate this with #inject to get a cough one liner:

irb(main):012:0> b = a.inject([]) {|c,x| p x; x % 2 == 0 and c << x
and c.size >= 5 and break c or c}
1
2
3
4
5
6
7
8
9
10
=> [2, 4, 6, 8, 10]

:slight_smile:

Kind regards

robert

Yes Robert you are right… I’ve used “next” instead of “break”…

Robert K. wrote in post #989144:

On Fri, Mar 25, 2011 at 8:37 AM, Saravanan K.
[email protected] wrote:

Hi venkat,

Here is the better solution,

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
b = []
a.each do |x|
next if b.length >= 5
b << x if x % 2 ==0
end

puts b

Cheers,
Sarav

Venkat S. wrote in post #989142:

Thanks Saravanan for your reply. I thought of doing this .
But the problem is array size. Here I defined array with 15 elements.
What if we have 1000 of elements in array.