Reputation: 11
I'm learning on codeacademy and I am trying to make a redacted program work for each situation including periods and commas next to a redacted word. My code that works as intended:
puts "Please enter a value"
text = gets.chomp
puts "To redact?"
redact = gets.chomp
words = text.split(" ")
words.each do |foo|
if foo.downcase == redact
print "REDACTED "
elsif foo.downcase == (redact + ".")
print "REDACTED" + "." + " "
elsif foo.downcase == (redact + ",")
print "REDACTED" + "," + " "
else
print foo + " "
end
end
I get this in the console:
Please enter a value
I am master, right?
To redact?
master
I am REDACTED, right? ["I", "am", "master,", "right?"]
But, the code that does not work:
puts "Please enter a value"
text = gets.chomp
puts "To redact?"
redact = gets.chomp
words = text.split(" ")
words.each do |foo|
if foo.downcase == redact
print "REDACTED "
elsif (foo.downcase == (redact + ".") || (redact + ","))
print "REDACTED" + "." + " "
else
print foo + " "
end
end
For the time being, ignore the fact that it would print a period even if it was supposed to be a comma. I'm curious about why when I run this program, every word is redacted in the console.
Upvotes: 0
Views: 54
Reputation: 8355
elsif (foo.downcase == (redact + ".") || (redact + ","))
Let's break it down like the Ruby compiler would:
elsif XXX
looks for a boolean value XXX
(that is, in Ruby talk, it looks at the truthiness of XXX
)
foo.downcase == (redact + ".") || (redact + ",")
is evaluated. ==
binds less tight than ||
, so the term is split on the ==
first
foo.downcase
returns a string(redact + ".") || (redact + ",")
is just the operator ||
which is defined as "if the left operand is truthy, then evaluate to the left operand; else the right one". So ruby looks at the left operand:
redact + "."
is a non-empty string which by definition is always truthy, so the result of the ||
is the left side (no matter what redact
contains).So, traveling back up the tree, (redact + ".") || (redact + ",")
is evaluated to redact + "."
which is compared to foo.downcase
with the result you're experiencing.
A rubyish way to express what you mean by elsif (foo.downcase == (redact + ".") || (redact + ","))
would be:
elsif [ redact+".", redact+"," ].include? foo.downcase
(Or, alternatively, any number of other solutions, like regular expressions, string splitting etc. - but this variant would be closest to what you wrote, and pretty easy to read for someone familiar with Ruby idioms. Since it involves creating multiple strings and an array, this is not suggested in performance critical loops, but fine if performance/memory use is not an issue.)
Upvotes: 0
Reputation: 121020
Instead of [erroneous] check for foo
being either this or that, one might use regular expression:
foo.downcase =~ /\A#{redact}[.,]\z/
The above will be evaluated to truthy
when foo.downcase
matches the value of redact
followed by either a comma or a dot.
Upvotes: 0
Reputation: 12256
The statement foo.downcase == (redact + ".") || (redact + ",")
is always true in ruby. The equivalent of this statement is: foo.downcase == (redact + ".") || (redact + ",") != nil
What you want to test instead is:
foo.downcase == (redact + ".") || foo.downcase == (redact + ",")
Ruby can evaluate anything as a boolean. Only nil
and False
will be evaluated to false.
Upvotes: 1