Andy - 8 months ago 42

Ruby Question

Just a quick question -- I'm probably overlooking something here.

The below method outputs the first 2 odd numbers correctly: [1,3]

If I'm not mistaken, shouldn't I want the length of the array to eventually **equal** n? As I understand it, the length of the outputted array [1,3] is 2, which also represent the first n-many odds: 2.

As such, the comparison in line 6 would now be **<=** rather than **<**

However, if I do that, first_n_odds(2) would now equal [1,3,5], which gives me the first *three* odds. What's going on here?

Thanks!

`def first_n_odds(n)`

array = []

current_number = 0

while array.length < n

if current_number % 2 == 1

array << current_number

end

current_number += 1

end

return array

end

puts first_n_odds(2) # output is [1,3]

Answer

Let's do your example with `n == 2`

.

Iteration 1: `array.length == 0`

.
Iteration 2: `array.length == 1`

.

Both of these values are `< 2`

. Now if you change `<`

to `<=`

, you'd have a 3rd iteration where `array.length == 2`

since your check happens *before* adding the new element to the array.

Since you seem to be fairly new to Ruby, here are some ways to define the method in a more idiomatic way:

```
# Mapping over a range
def first_n_odds_1(n)
(0...n).map { |x| x * 2 + 1 }
end
# Mapping over an Enumerator
def first_n_odds_2(n)
n.times.map { |x| x * 2 + 1}
end
# Using Numeric#step + Enumerable#take
def first_n_odds_3(n)
1.step(Float::INFINITY, 2).take(n)
end
# A more explicit version of the previous method
def first_n_oods_4(n)
1.step(by: 2, to: Float::INFINITY).take(n)
end
```

Source (Stackoverflow)