Ruby で文字列の表示幅をもとめるおはなし
Ruby には文字列の表示幅を求めるメソッドがありません(ニッチ)。 要は ASCII 文字を1文字、非 ASCII 文字(= マルチバイト文字)を2文字としてカウントしたいんです(ニッチ)(ニッチ)。
こんな感じで求めてみる
"hogeふが".chars => ["h", "o", "g", "e", "ふ", "が"] # String#chars で1文字ずつにばらす ["h", "o", "g", "e", "ふ", "が"].map { |c| c.ascii_only? ? 1 : 2 } => [1, 1, 1, 1, 2, 2] # ASCII 文字を1文字、非 ASCII 文字を2文字としてカウント [1, 1, 1, 1, 2, 2].inject(0, &:+) => 8 # みんなだいすき Enumerable#inject で合計を求める
できた
class String def width self.chars.map{ |c| c.ascii_only? ? 1 : 2 }.inject(0, &:+) end end "hogeふが".width => 8
だがしかし
ちょっと効率がわるい(each が2回まわる)
作戦変更
"hogeふが".chars.reject(&:ascii_only?) => ["ふ", "が"] # Array#reject で ASCII 文字を取り除く(= 非 ASCII 文字を抽出) "hogeふが".length + ["ふ", "が"].length => 8
できた(2回目)
class String def width self.length + self.chars.reject(&:ascii_only?).length end end "hogeふが".width => 8
まとめ
Enumerable#inject だいすき