Arrays - create, filtering and returning

  • Thread starter Yannick Turgeon
  • Start date
Y

Yannick Turgeon

Hello all,

I just started to learn Ruby and I've got a couple of questions concerning
arrays and particularly creating and returning "filtered" arrays.

--------------------------
1- Say I want to create an array of all pair numbers from 2 to 100, do I
have to write:

a = []
2.step(100, 2){|v| a.push(v)}

is there a way I could do in one single line:
a = ...

Or more generally, is there a way to collect and return, in an array, values
extracted at each loop inside a block without using a variable previously
created outside that block?

--------------------------
2- From this newly created array, if I want to extract only those numbers
mutiple of 5 (10,20, ...), are you coding something like:

b = a.collect{|v| v.modulo(5) == 0 ? v : nil}.compact

It seems like a miss a function here which should be called something like
"extract" or "find_all".
--------------------------


Thanks for your feedbacks.


Yannick
 
A

Assaph Mehr

Hi and welcome to Ruby!

I just started to learn Ruby and I've got a couple of questions concerning
arrays and particularly creating and returning "filtered" arrays.

Look at the documentation for Enumerable module as well as the Array
class.
You can find the docos at http://www.ruby-doc.org/
and specifically:
http://www.ruby-doc.org/core/classes/Enumerable.html
http://www.ruby-doc.org/core/classes/Array.html
--------------------------
1- Say I want to create an array of all pair numbers from 2 to 100, do I
have to write:

a = []
2.step(100, 2){|v| a.push(v)}

is there a way I could do in one single line:
a = ...

a = (2..100).select { |n| n%2 == 0 }

We create a Range object (2..100), and then select the even numbers.
You can also transform the range into an array of integer numbers via
the #to_a method.

The #select and #reject methods allow you to take a collection and
either keep or throw out the relevant objects. Both return a copy of
the original array.

Another way to do it is to use the versatile #inject method:
a = (2..100).inject([]) { |acc, n| acc << n if n%2 == 0; acc }
Again we create a Range object. Inject takes a starting value (an empty
array here) and passes to the block the accumulator and the element.
here we append to the accumulator if the element is even, and return
the accumulator for the next iteration.
This is especially useful if you want to do things like sum the
elements:
a = (2..100).inject(0) { |acc, n| acc + n }
Here there is no need to explicitly return the accumulator, as the last
element in the block is what we need for the next element.
--------------------------
2- From this newly created array, if I want to extract only those numbers
mutiple of 5 (10,20, ...), are you coding something like:

b = a.collect{|v| v.modulo(5) == 0 ? v : nil}.compact

It seems like a miss a function here which should be called something like
"extract" or "find_all".

Usually if you think of a method name it's already in there, and does
what you expect :)

b = a.find_all { |n| n%5 == 0 }

Look also at enumerable#grep. Notice that you can also chain methods:

b = (2..100).select { |n| n%2 == 0 }.select { |n| n%5 == 0 }

Of course for performance you are likely to put both conditions in the
one block. But this is useful if you want to do other processing on the
elements.


HTH,
Assaph
 
Y

Yannick Turgeon

Hello Assaph,

Thank you very much for your message. I had actually found www.ruby-doc.org
and read a lot but I didn't realise Array has Enumerable module... and a
lot more method to look at. I had read every array method with deception
about the limitation I had. I cannot even beleive I asked for a "find_all"
method when it was actually existing. I even tried it before asking here
but I used () instead of {}. Your post is full of interesting information
too, like "inject" method and range utilisation. It made me read a lot and
learn a lot. I really appreciated.

Yannick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top