ruby for loop using range class instead of fixnum? - ruby

for i in [0..4] do
puts i + 1
end
undefined method `+' for 0..4:Range (NoMethodError)
Why is it not treating each number in the range as a fixnum within the loop?

[0..4] is actually array with one range element, the same as [(0..4)]. You need to change it to (0..4).

Write instead:
for i in 0..4 do
Otherwise you don't have a range, you have an array containing 1 range.

There are different ways to achive a goal:
0.upto(4) { |i|
puts i
}
0.step(4, 1) { |i|
puts i
}
5.times { |i| # 5 for inclusive
puts i
}
for i in 0..4
puts i
end
Everything will output:
# ⇒ 0
# ⇒ 1
# ⇒ 2
# ⇒ 3
# ⇒ 4
Hope it helps.

Related

How do print odd numbers using block { }

I am trying to print my array with just odd numbers using the block method but i am not too sure how to.
I can print odd numbers using no block but do but do not know how to implement it into the block method { }
#non block method
array = [1,2,3,4,5,6,7,8]
array.each do |i|
if i % 2 == 0
puts "#{i}"
end
end
#output of 2 4 6 8
#block method not sure how
array = [1,2,3,4,5,6,7,8]
array.each {|i| put i if i % 2 == 0 end }
#expected output should be 2 4 6 8
Thank you in advanced !
your block is almost correct you just need to remove the end as it's an inline (or trailing) if method, you also need to use puts and not put
array.each {|i| puts i if i % 2 == 0 }
also, note that ruby has a .even? and .odd? methods you can call on integers
array.each {|i| puts i if i.odd? }
Another option is to select the even? elements and print them afterwards:
array.select(&:even?).each { |i| puts i }
Or alternatively via reject and odd?:
array.reject(&:odd?).each { |i| puts i }
The each call isn't really needed, as you can pass an entire array to puts and it will print each element on a separate line:
puts array.select(&:even?)
# or
puts array.reject(&:odd?)
All of the above will generate the same output:
2
4
6
8

Iterate through first n elements of array - if that many exist

I am looking for a more elegant, 'Ruby-ists' way to do the following. Is there any cleaner way to do this?
i=0
array.each do |x|
break if x.empty?
puts x
i+=1
break if i>4
end
I saw that you were calling #empty? on the elements in your array and quitting when you see the first empty element. If you want to preserve that behavior, you could do:
array.first(4).each do |x|
break if x.empty?
puts x
end
A fancier way would be:
array.take_while { |i| !i.empty? }.first(4).each do |i|
puts i
end
I am not sure how many elements you want to print; please note that my examples will print at most 4 elements, whereas your code was printing up to 5.
I'd suggest Array#first as follows:
array.first(4).each do |x|
puts x
end
If you only want to accept the first so many non-nil entries, then filter them out using Array#compact:
array.compact.first(4).each do |x|
puts x
end
If you are concerned about empty values then you could still chain the filters using Array#reject:
array.reject(&:empty?).first(4).each do |x|
puts x
end
Another way:
def printem(a,n)
puts a[0, [a.index(&:empty?) || n, n].min]
end
printem [[], [2],[3],[4],[5],[6]], 4
# <prints nothing>
printem [[1],[2], [],[4],[5],[6]], 4
# 1
# 2
printem [[1],[2],[3],[4],[5],[6]], 4
# 1
# 2
# 3
# 4
printem [[1],[2],[3],[4],[5],[6]], 7
# 1
# 2
# 3
# 4
# 5
# 6

How do I make a function that accepts an anonymous function using 'do' keyword syntax?

When using array.each you can specify the function in two forms:
Curly Braces:
a = [1,2,3]
a.each { |x| puts x * x }
Output:
1
4
9
=> [1, 2, 3]
'do' Syntax:
a = [1,2,3]
a.each do |x|
puts (x * x)
end
Output:
1
4
9
=> [1, 2, 3]
Question:
How can I replicate the 'do' syntax style with my own custom function? The closest to the curly brace style I can get is:
What I've tried:
def PutWith2Arg(proc)
puts proc.call(2)
end
PutWith2Arg(Proc.new { |x| x + 100 })
Output:
102
=> nil
The do |foo| … end and { |foo| … } syntaxes are equivalent. These are 'blocks' in Ruby, and any method can get them. To call them you need to either:
def my_method # No need to declare that the method will get a block
yield(42) if block_given? # Pass 42 to the block, if supplied
end
my_method do |n|
puts "#{n} times 2 equals #{n*2}"
end
#=> "42 times 2 equals 84"
my_method{ |n| puts "#{n} times 2 equals #{n*2}" }
#=> "42 times 2 equals 84"
my_method # does nothing because no block was passed
or, for more sophisticated uses:
def my_method( &blk ) # convert the passed block to a Proc named blk
blk.call( 42 ) if blk
end
# Same results when you call my_method, with or without a block
The latter style is useful when you need to pass the block on to another method. If you have a Proc or Lambda referenced by a variable, you can pass it to a method as the block for that method using the & syntax:
def my_method( &blk ) # convert the passed block to a Proc named blk
[1,2,3].each( &blk ) # invoke 'each' using the same block passed to me
end
my_method{ |x| p x=>x**2 }
#=> {1=>1}
#=> {2=>4}
#=> {3=>9}
For more details, this webpage is fairly instructive.

ruby array input

I am trying to write a small function with ruby that gets fed a array from the user and then sums up the data in the array. I have written it as
def sum(a)
total = 0
a.collect { |a| a.to_i + total }
end
The function then runs through a rspec, which tests it by initially feeding into it a blank array. This this causes the following error
sum computes the sum of an empty array
Failure/Error: sum([]).should == 0
expected: 0
got: [] (using ==)
So its telling me that when it feeds the blank array in, its supposed to get 0 but instead its getting the array. I tried putting in a if statement written as
def sum(a)
total = 0
a.collect { |a| a.to_i + total }
if total = [] then { total = 0 end }
end
but it gives me an error saying
syntax error, unexpected '}', expecting => (SyntaxError)
what am I doing wrong?
You shouldn't use map/collect for this. reduce/inject is the appropriate method
def sum(a)
a.reduce(:+)
# or full form
# a.reduce {|memo, el| memo + el }
# or, if your elements can be strings
# a.map(&:to_i).reduce(:+)
end
See here: How to sum array of numbers in Ruby?
and here: http://www.ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject
def sum(a)
array.inject(0) {|sum,x| sum + x.to_i }
end
gets.split.map(&:to_i).inject(:+)

How do I know what iteration I'm in when using the Integer.times method?

Let's say I have
some_value = 23
I use the Integer's times method to loop.
Inside the iteration, is there an easy way, without keeping a counter, to see what iteration the loop is currently in?
Yes, just have your block accept an argument:
some_value.times{ |index| puts index }
#=> 0
#=> 1
#=> 2
#=> ...
or
some_value.times do |index|
puts index
end
#=> 0
#=> 1
#=> 2
#=> ...
3.times do |i|
puts i*100
end
In this way, you can replace 3 with any integer you like, and manipulate the index i in your looped calculations.
My example will print the following, since the index starts from 0:
# output
0
100
200

Resources