John John - 4 months ago 7
Ruby Question

Ruby arrays methods and outputs

I have worked out the following code un ruby that when given a number should return all the even numbers between 1 and the number and print them out in the following format:

22
4444
666666
etc...


This is the code so far:

def pattern(n)
n == 1 ? "" : arr = (1..n).select {|i| i if i % 2 == 0}.each {|item| return (item.to_s * item)}
end


This works when the number is less than 4. However, with any number greater than four it will only return the following:

22


I think that this may have something to do with the return in the block. However, when using print or puts this returns the individual aray element as follows:

[2]


Ideas for a way around this so that I can achieve the desired output?

Answer

This code fixes your issue:

def pattern(n)
  n == 1 ? "" : arr = (1..n).select {|i| i if i % 2 == 0}.map {|item| (item.to_s * item)}
end

Note that I'm using map instead of each, and I'm not using a return. The return meant that you didn't actually finish looping over the numbers... as soon as you got to 2 you returned from the function.

map is what you want if you want to build up a new array with the results.

EDIT

A little more cleanup:

def pattern(n)
  n == 1 ? "" : (1..n).select {|i| i.even?}.map {|item| item.to_s * item}
end

The arr = is unnecessary. Your block in a select should just return true or false... you could also use just i % 2 == 0 in there, but even? happens to exist. Also, the parentheses around item.to_s * item are unnecessary.

EDIT 2

Per comments below, if you want a single string, maybe this is what you're looking for (added .join("\n")):

def pattern(n)
  n == 1 ? "" : (1..n).select {|i| i.even?}.map {|item| item.to_s * item}.join("\n")
end

EDIT 3

When returning a string, you can also skip the n==1 special case, since joining an empty array will just return an empty string:

def pattern(n)
  (1..n).select {|i| i.even?}.map {|item| item.to_s * item}.join("\n")
end