KyuuQ
KyuuQ

Reputation: 65

Performing operations on each line of a string

I have a string named "string" that contains six lines. I want to remove an "Z" from the end of each line (which each has) and capitalize the first character in each line (ignoring numbers and white space; e.g., "1. apple" -> "1. Apple").

I have some idea of how to do it, but have no idea how to do it in Ruby. How do I accomplish this? A loop? What would the syntax be?

Upvotes: 0

Views: 622

Answers (2)

Alvin S. Lee
Alvin S. Lee

Reputation: 5182

I would approach this by breaking your problem into smaller steps. After we've solved each of the smaller problems, you can put it all back together for a more elegant solution.

Given the initial string put forth by falsetru:

s = <<EOS
1. applez
2. bananaz
3. catz
4. dogz
5. elephantz
6. fruitz
EOS

1. Break your string into an array of substrings, separated by the newline.

substrings = s.split(/\n/)

This uses the String class' split method and a regular expression. It searches for all occurrences of newline (backslash-n) and treats this as a delimiter, splitting the string into substrings based on this delimiter. Then it throws all of these substrings into an array, which we've named substrings.

2. Iterate through your array of substrings to do some stuff (details on what stuff later)

substrings.each do |substring|
.
# Do stuff to each substring
.
end

This is one form for how you iterate across an array in Ruby. You call the Array's each method, and you give it a block of code which it will run on each element in the array. In our example, we'll use the variable name substring within our block of code so that we can do stuff to each substring.

3. Remove the z character at the end of each substring

substrings.each do |substring|
  substring.gsub!(/z$/, '')
end

Now, as we iterate through the array, the first thing we want to do is remove the z character at the end of each string. You do this with the gsub! method of String, which is a search-and-replace method. The first argument for this method is the regular expression of what you're looking for. In this case, we are looking for a z followed by the end-of-string (denoted by the dollar sign). The second argument is an empty string, because we want to replace what's been found with nothing (another way of saying - we just want to remove what's been found).

4. Find the index of the first letter in each substring

substrings.each do |substring|
  substring.gsub!(/z$/, '')
  index = substring.index(/[a-zA-Z]/)
end

The String class also has a method called index which will return the index of the first occurrence of a string that matches the regular expression your provide. In our case, since we want to ignore numbers and symbols and spaces, we are really just looking for the first occurrence of the very first letter in your substring. To do this, we use the regular expression /[a-zA-Z]/ - this basically says, "Find me anything in the range of small A to small Z or in big A to big Z." Now, we have an index (using our example strings, the index is 3).

5. Capitalize the letter at the index we have found

substrings.each do |substring|
  substring.gsub!(/z$/, '')
  index = substring.index(/[a-zA-Z]/)
  substring[index] = substring[index].capitalize
end

Based on the index value that we found, we want to replace the letter at that index with that same letter, but capitalized.

6. Put our substrings array back together as a single-string separated by newlines.

Now that we've done everything we need to do to each substring, our each iterator block ends, and we have what we need in the substrings array. To put the array back together as a single string, we use the join method of Array class.

result = substrings.join("\n")

With that, we now have a String called result, which should be what you're looking for.

Putting It All Together

Here is what the entire solution looks like, once we put together all of the steps:

substrings = s.split(/\n/)
substrings.each do |substring|
  substring.gsub!(/z$/, '')
  index = substring.index(/[a-zA-Z]/)
  substring[index] = substring[index].capitalize
end
result = substrings.join("\n")

Upvotes: 1

falsetru
falsetru

Reputation: 368924

Using regular expression (See String#gsub):

s = <<EOS
1. applez
2. bananaz
3. catz
4. dogz
5. elephantz
6. fruitz
EOS

puts s.gsub(/z$/i, '').gsub(/^([^a-z]*)([a-z])/i) { $1 + $2.upcase }

# /z$/i - to match a trailing `z` at the end of lines.
# /^([^a-z]*)([a-z])/i - to match leading non-alphabets and alphabet.
#                        capture them as group 1 ($1), group 2 ($2)

output:

1. Apple
2. Banana
3. Cat
4. Dog
5. Elephant
6. Fruit

Upvotes: 2

Related Questions