4

New to Ruby here. I am attempting to put an if else statement in an array to send a string if a certain modulus == 0. for the life of me i can't find it anywhere. I am sure someone will find it ridiculously simple.

a = *(1..100)
a.each { |i| puts "three" if i % 3 == 0 elsif puts "five" if i % 5 == 0 else puts i}

Just not sure of the correct syntax. Still new to ruby and am trying to learn the syntax. Took a C class last semester and my brain keeps wanting to put in C syntax.

When I leave it as

a = *(1..100)
a.each { |i| puts "three" if i % 3 == 0}

it works fine, just trying to figure out how to add if else to it. Help is appreciated.

The answers below were really helpful. I am trying to take it a step further and call it into a function. It keeps returning 5, and not "five", or 3, and not "three".

here is my function:

def array_mod
a = *(1..100)
a.each { |i| if i % 3 == 0  && i % 5 == 0; i = "fifteen" elsif i % 3 == 0; i = "three" elsif i % 5 == 0; i = "five" else i = i end }

end

and here is my attempt at calling it.

require "minitest/autorun"
require_relative "array_modulus.rb"



class TestArrayFunction < Minitest::Test


def test_array1

    results = array_mod

    assert_equal(100, results.length)
end

def test_array2

    results = array_mod
    assert_equal("three", results[2])
end


end

I was told it is not updating my array. Thanks again.

0

5 Answers 5

6

The syntax of a conditional expression in Ruby is:

if c_1 then e_1 elsif c_2 then e_2 elsif c_3 then e_3 … elsif c_n then e_n else e_nplus1 end

where c_1c_n and e_1e_nplus1 can be arbitrary Ruby expressions.

It is possible to use an expression separator (i.e. ; or newline) instead of the then keyword to separate the parts of the conditional expression.

With semicolon (this usage is non-idiomatic):

if c_1; e_1 elsif c_2; e_2 elsif c_3; e_3 … elsif c_n; e_n else e_nplus1 end

With newlines:

if c_1
  e_1
elsif c_2
  e_2
elsif c_3
  e_3
# …
elsif c_n
  e_n
else
  e_nplus1
end

If you use newlines, you can optionally also use the then keyword, but that is non-idiomatic, too:

if c_1
then e_1
elsif c_2
then e_2
elsif c_3
then e_3
# …
elsif c_n
then e_n
else
  e_nplus1
end

So, in your case, the correct syntax would be:

# idiomatic
a.each { |i| if i % 3 == 0 then puts "three" elsif i % 5 == 0 then puts "five" else puts i end }

# non-idiomatic
a.each { |i| if i % 3 == 0; puts "three" elsif i % 5 == 0; puts "five" else puts i end }

# idiomatic
a.each { |i|
  if i % 3 == 0
    puts "three"
  elsif i % 5 == 0
    puts "five"
  else
    puts i
  end
}

# non-idiomatic
a.each { |i|
  if i % 3 == 0
  then puts "three"
  elsif i % 5 == 0
  then puts "five"
  else
    puts i
  end
}

However, for such a chain of if / elsif, it is typically more idiomatic to use a case expression:

# idiomatic
case when c_1 then e_1 when c_2 then e_2 when c_3 then e_3 … when c_n then e_n else e_nplus1 end

# non-idiomatic
case when c_1; e_1 when c_2; e_2 when c_3; e_3 … when c_n; e_n else e_nplus1 end

# idiomatic
case
when c_1
  e_1
when c_2
  e_2
when c_3
  e_3
# …
when c_n
  e_n
else
  e_nplus1
end

# non-idiomatic
case
when c_1
then e_1
when c_2
then e_2
when c_3
then e_3
# …
when c_n
then e_n
else
  e_nplus1
end

Which in your case would look like this:

# idiomatic
a.each { |i| case when i % 3 == 0 then puts "three" when i % 5 == 0 then puts "five" else puts i end }

# non-idiomatic
a.each { |i| case when i % 3 == 0; puts "three" when i % 5 == 0; puts "five" else puts i end }

# idiomatic
a.each { |i|
  case
  when i % 3 == 0
    puts "three"
  when i % 5 == 0
    puts "five"
  else
    puts i
  end
}

# non-idiomatic
a.each { |i|
  case
  when i % 3 == 0
  then puts "three"
  when i % 5 == 0
  then puts "five"
  else
    puts i
  end
}

Note that the conditional expressions (both if and case) are expressions, not statements. There are no statements in Ruby, everything is an expression, everything evaluates to a value. A conditional expression evaluates to the value of the expression in the branch that was taken.

So, you could also write it like this:

# idiomatic
a.each { |i| puts(if i % 3 == 0 then "three" elsif i % 5 == 0 then "five" else i end) }

# non-idiomatic
a.each { |i| puts(if i % 3 == 0; "three" elsif i % 5 == 0; "five" else i end) }

# idiomatic
a.each { |i|
  puts(if i % 3 == 0
    "three"
  elsif i % 5 == 0
    "five"
  else
    i
  end)
}

# non-idiomatic
a.each { |i|
  puts(if i % 3 == 0
  then "three"
  elsif i % 5 == 0
  then "five"
  else
    i
  end)
}

# idiomatic
a.each { |i| puts(case when i % 3 == 0 then "three" when i % 5 == 0 then "five" else i end) }

# non-idiomatic
a.each { |i| puts(case when i % 3 == 0; "three" when i % 5 == 0; "five" else i end) }

# idiomatic
a.each { |i|
  puts(case
  when i % 3 == 0
    "three"
  when i % 5 == 0
    "five"
  else
    i
  end)
}

# non-idiomatic
a.each { |i|
  puts(case
  when i % 3 == 0
  then "three"
  when i % 5 == 0
  then "five"
  else
    i
  end)
}
Sign up to request clarification or add additional context in comments.

2 Comments

Your reply was extremely helpful. I tried to ask a second question in this box but i guess they don't want you posting code in these boxes, so I updated my top question. Thanks again man.
That's because when you have a question, you should write a question, not a comment ;-)
2

You can use an if to qualify a single statement, but once you move into elsif/else territory, it's necessary to break it up like a normal C-style if statement:

a.each do |i|
  if i % 3 == 0 
    puts "three" 
  elsif i % 5 == 0
    puts "five" 
  else
    puts i
  end
end

2 Comments

ok. I didn't know if I had to put an else inside the brackets. I am used to C's using parentheses and curled brackets for everything. Ruby hardly uses them from what ive seen so far. But the |i| , is that labeling the following code as "i"? Or is it a temporary labelling i for that block? Thanks though, this is exactly what I was curious about.
@Mike I'm not sure you mean by "inside the brackets." The else is lined up with the if, just like it would be in C (minus the curly braces). Yeah, curlies aren't used the same way... they're used to define blocks in Ruby (similar to do..end). The |i| is just declaring the loop variable(s); each time through the loop, i will be set to the next element of a.
2

Here is the syntax.

a = *(1..100)
a.each do |i|
  if i % 3 == 0
    puts "three"
  elsif i % 5 == 0
    puts "five"
  else
    puts i
  end
end

Keep in mind that each will return Enumerator, but not exact value. You need to use return keyword to return value. Here is the docs

2 Comments

Keep in mind that each will return Enumerator, but not exact value what do you mean?
I meant that each will return unchanged array in that case.
1

Please see if the below code helps

def abc
   a = *(1..100)
   a.each do |i|
       if i % 3 == 0 
       puts "three"
       elsif i % 5 == 0
       puts "five"
       else
         puts i
       end
     end
   end

=> :abc

2.3.0 :013 > abc

this gives the desired output in irb mode.

Comments

1

Or, if you want to emphasize, that there is always a puts and just the output value changes:

puts(
  if i%3==0
    'three'
  elsif i%5==0
    'five'
  else
    i
  end
) 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.