'Capitalize every nth character of each word in a string in Ruby

I need to capitalize every 'nth' character for each word in a string (every multiple of 4-th character in this example, so character 4, 8, 12 etc).

I came up with the code below (not very elegant I know!) but it only works for words which length < 8.

'capitalize every fourth character in this string'.split(' ').map do |word|
  word.split('').map.with_index do |l,idx|
  idx % 3 == 0 && idx > 0 ? word[idx].upcase : l 
  end 
  .join('')
end 
.flatten.join(' ')

Anybody could show me how to capitalize every 4th character in words which length > 8?

Thanks!



Solution 1:[1]

str = 'capitalize every fourth character in this string'

idx = 0
str.gsub(/./) do |c|
  case c
  when ' '
    idx = 0
    c
  else
    idx += 1
    (idx % 4).zero? ? c.upcase : c
  end
end
  #=> "capItalIze eveRy fouRth chaRactEr in thiS strIng"

Solution 2:[2]

As an option, you can just modify the nth character in the string if it exists by accessing the character by index:

'capitalizinga every fourth character in this string'.split(' ').map do |word|
  (3..word.length).step(4) do |x|
    c = word[x]
    word[x] = c.upcase if c
  end
  word
end.join(' ')

# capItalIzinGa eveRy fouRth chaRactEr in thiS strIng

Here is the method step or Range class is used, so each fourth index could be calculated: 3, 7, 11, etc...

Solution 3:[3]

I think the easiest way is to use a regex with substitution:

'capitalize every fourth character in this string'
  .gsub(/([\w]{3})(\w)|([\w]{1,3})/) {
    "#{$1}#{$2.to_s.upcase}#{$3}"
  }

# => capItalIze eveRy fouRth chaRactEr in thiS strIng

This uses 2 alternatives with captured groups - the first alternative matches 4 characters and the second everything with 1 to 3 characters. Group $1 will match exactly three letters and group $2 the fourth letter within a 4-letter block - while group $3 will match remainders of a longer word as well words shorter than 4 characters. You can then replace group $2 globally with gsub. Also you need to do $2.to_s in case $2 is nil (or catch that scenario with a ternary operator).

You can inspect the regex here and try the code here

Solution 4:[4]

> str.split(" ").map{|word| 
    word.chars.each_with_index{|c,i| 
      c.upcase! if (i > 0 && (i+1)%4 == 0)}.join}.join(" ")
#=> "capItalIze eveRy fouRth chaRactEr in thiS strIng"

Solution 5:[5]

def capitalize_each_nth_char(str, n)
  str.chars.each_slice(n).to_a.each { |arr| arr[-1] = arr[-1].upcase if arr.size == n }.join('')
end

Here is the explanation,

str.chars # will give array of characters 

str.chars.each_slice(n) # will give an enumerator as, #<Enumerator: ...> 

str.chars.each_slice(n).to_a # will give an array of arrays 

arr[-1].upcase # it will capitalize the last element i.e. 4th element of each array

if arr.size == n # it will prevent to capitalize last element of sub-array if it's size is less than n(in our case 4)

str.chars.each_slice(n).to_a.each { |arr| arr[-1] = arr[-1].upcase if arr.size == n } # it will give array of subarray where every subarray last element is capital

str.chars.each_slice(n).to_a.each { |arr| arr[-1] = arr[-1].upcase if arr.size == n }.join('') # it will give the final result as, "capItalIze EverY foUrth chaRactEr iN thIs sTrinG"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Cary Swoveland
Solution 2
Solution 3 wiesion
Solution 4
Solution 5