Apply .capitalize on an Cyrillic array in ruby

296 Views Asked by At

I want to capitalise the string elements in the array with ruby

This is my code:

headermonths = ["января","февраля","марта","апреля","мая","июня","июля","августа","октября","ноября","декабря"]

headermonths.each {|month| month.capitalize!}
puts headermonths

I get the following output:

января
февраля
марта
апреля
мая
июня
июля
августа
октября
ноября
декабря

if print the array with:

 print headermonths    

I get the following

["\u044F\u043D\u0432\u0430\u0440\u044F", "\u0444\u0435\u0432\u0440\u0430\u043B\u044F", "\u043C\u0430\u0440\u0442\u0430", "\u0430\u043F\u0440\u0435\u043B\u044F", "\u043C\u0430\u044F", "\u0438\u044E\u043D\u044F", "\u0438\u044E\u043B\u044F", "\u0430\u0432\u0433\u0443\u0441\u0442\u0430", "\u043E\u043A\u0442\u044F\u0431\u0440\u044F", "\u043D\u043E\u044F\u0431\u0440\u044F", "\u0434\u0435\u043A\u0430\u0431\u0440\u044F"]

But I would like to have an output like:

Января Февраля Марта Апреля Мая Июня Июля Августа Октября Ноября Декабря

How does I achieve this with a ruby method?

3

There are 3 best solutions below

0
On BEST ANSWER

You can use the unicode gem

require 'unicode'

headermonths = ["января","февраля","марта","апреля","мая","июня","июля","августа","октября","ноября","декабря"]

headermonths.map! {|month| Unicode::capitalize month }
puts headermonths
# >> ["Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля", "Августа", "Октября", "Ноября", "Декабря"]
3
On

Stand-alone solution :

# From : https://en.wikipedia.org/wiki/Cyrillic_alphabets :
upcase   = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"
downcase = "абвгдежзийклмнопрстуфхцчшщьюя"

headermonths = ["января","февраля","марта","апреля","мая","июня","июля","августа","октября","ноября","декабря"]

headermonths.each{|word| word[0] = word[0].tr(downcase,upcase)}
# => ["Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля", "Августа", "Октября", "Ноября", "Декабря"]

If you want to use it with words in latin and cyrillic alphabets :

headermonths.each{|word| word[0] = word[0].tr(downcase,upcase).upcase }

With ActiveSupport

You can use ActiveSupport::Multibyte :

require 'active_support/core_ext/string/multibyte'
"января".mb_chars.capitalize.to_s #=> "Января"

So your script becomes :

require 'active_support/core_ext/string/multibyte'

headermonths = ["января","февраля","марта","апреля","мая","июня","июля","августа","октября","ноября","декабря"]

headermonths.map!{|word| word.mb_chars.capitalize.to_s}
#=> ["Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля", "Августа", "Октября", "Ноября", "Декабря"]

Ruby 2.4

The code in your question would work just as expected with Ruby 2.4.

See "Case sensitivity for unicode characters" here.

5
On

The example below is a robust capitalize version, that works in any ruby starting with 1.9 but for cyrillic only due to -32 hardcoded.

NB: thanks and credits go to @Stefan and @EricDuminil, who lead me to the right direction

headermonths = %w|января февраля марта апреля мая июня
                  июля августа октября ноября декабря|
puts (headermonths.each do |s|
  s[0] = (s[0].ord - 32).chr(Encoding::UTF_8) 
end.inspect)
#⇒ ["Января", "Февраля", "Марта", "Апреля", "Мая", "Июня",
#   "Июля", "Августа", "Октября", "Ноября", "Декабря"]