Question

This is a straightforward and simple question. In the code below, this should replace the character specified with an underscore, but it isn't. I've looked at the documentation for both .each_char and .gsub and this combination should work. Why does this snippet of code not work?

string = "string"
new_string =string.each_char do |char|
  if char == "i"
    string.gsub(/char/,"_")
  end
end

puts new_string

The above code should output "str_ing". Right?

Was it helpful?

Solution 2

There are a couple of things wrong with the code.

First the regular expression /char/ is looking for the literal characters char, not the contents of the variable. What you probably want is /#{char}/ which evaluates char and creates a regexp with its contents.

Next, look at the difference between gsub and gsub!. gsub, which is what you are using, creates a new string. Inside your block you create a new string, but then don’t do anything with it. It basically gets thrown away.

The each_char method returns the original string after yielding each character to the block. The string isn’t changed in the block, so at the end it is unchanged. If you used gsub! instead of gsub you will see what you expected, since the original string is altered.

However, don’t do this. In general you shouldn’t manipulate a data-structure like this whilst you are iterating over it. In this case it works okay, but it is not a habit you should get into. You cannot be sure how your manipulation is going to effect the iteration, and you could end up with unexpected results or errors.

In this case you can just use gsub! by itself:

new_string.gsub!(/i/, '_')

OTHER TIPS

The first issue is using char inside the regular expression. The char you're using is not the variable but text. The second issue is to define a new string inside a block:

string = "string"
string.each_char do |char|
  if char == "i"
    new_string = string.gsub(/#{char}/,"_")
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top