Ruby
unicode

Ruby でローマ数字の文字 (機種依存文字) をアルファベットに変換する


やりたいこと

例えば (U+2166) を VII に変換したい。


方法


愚直な方法

def replace_roman_numerals_with_alphabets(str)

conversions = {
'Ⅰ' => 'I', 'Ⅱ' => 'II', 'Ⅲ' => 'III', 'Ⅳ' => 'IV', 'Ⅴ' => 'V',
'Ⅵ' => 'VI', 'Ⅶ' => 'VII', 'Ⅷ' => 'VIII', 'Ⅸ' => 'IX', 'Ⅹ' => 'X',
'Ⅺ' => 'XI', 'Ⅻ' => 'XII'
}.freeze

str.gsub(/[#{conversions.keys}]/, conversions)
end

replace_roman_numerals_with_alphabets('ファイナルファンタジーⅦ')
#=> "ファイナルファンタジーVII"

変換ルールを自分で用意するのは大変 :sob:


スマートな方法

def replace_roman_numerals_with_alphabets(str)

# Unicode の U+2160 から U+217F までがローマ数字。
roman_numerals_pattern = /[\u2160-\u217F]/
str.gsub(roman_numerals_pattern) { |char| char.unicode_normalize(:nfkd) }
end

replace_roman_numerals_with_alphabets('ファイナルファンタジーⅦ')
#=> "ファイナルファンタジーVII"

# ちなみに……
'ファイナルファンタジーⅦ'.unicode_normalize(:nfkd)
#=> "ファイナルファンタジーVII"

NFKD 形式 (あるいは NFKC 形式) で Unicode 正規化 することで、対応するアルファベットに分解することができる。


参考