文字を省略する際に、全角/半角を考慮する方法と、中間で省略する方法(Ruby)

【結論】

・文字を省略する際、全角/半角を考慮しないとレイアウトが崩れる場合がある。また末尾で省略すると、ファイル名なら拡張子が見えなくなるという問題が発生する。

・全角/半角を考慮する場合は、bytesizeメソッドを利用する

・中間で省略する場合は、文字を前半部と後半部に分けて結合する

【目次】

【本題】

文字の省略を柔軟に行いたい

前回文字を省略して表示する方法を投稿しましたが、これには欠点があります。

ryoutaku-jo.hatenablog.com

それは、文字を中間で省略できないという事と、文字の長さではなく数を基準に省略する位置を決めるので、同じ文字数で省略しても、全角/半角で最終的な長さが大きくズレてしまうという事です。

#文字を中間で省略できない
str = "abcdefg"
str.truncate(6)
=> "abc..."
#同じ文字数で省略しても、全角/半角で最終的な長さが大きくズレてしまう
short = "abcdefghijklnmop"
long = "あいうえおかきくけこさしすせそ"

short.truncate(10)
=> "abcdefghij..."

long.truncate(10)
=> "あいうえおかきくけこ..."

文字が末尾で省略されてしまうと、ファイル名を出力する場合は、拡張子が見えないという問題が発生します。

全角と半角で最終的な長さが異なると、意図せずレイアウトが崩れてしまう要因となり得ます。

この問題に対処する方法を、今回はまとめます。

文字を中間で省略する

今回の方法は、文字を前半部と後半部で分けて、間に「...」を挟んで結合するというやり方です。

str = "abcdefghijk"
str_size = str.size
split_point = 2

str[0, split_point] + '...'+ str[str_size-split_point, str_size] 
=> "ab...jk"

この様にして、文字を中間で省略する事が可能です。

全角/半角を見分ける

Rubyには全角を見分けるメソッドはありませんが、文字のバイト数を調べるメソッドは存在します。

https://ref.xaio.jp/ruby/classes/string/bytesize

文字のバイト数は、半角で1バイト、全角で3バイトなので、この情報を基に識別します。

例えば、全角を半角の2倍として、文字数が半角10文字相当より多い場合は、前半・後半を2文字づつに分割して中間で省略する場合の、下記の様に行います。

def truncate_str(str)
  size = str.size
  byte = str.bytesize
  total_size = ((byte - size) / 2) + size
  if total_size > 10
    split_point = 2
    str[0..split_point-1] + '...' + str[(size - split_point)..size]
  else
    str
  end
end

short = "abcdefghij"
long = "あいうえおかきくけこ"

truncate_str(short)
=> "abcdefghij"

truncate_str(long)
=> "あい...けこ"

これで全角と半角で長さに大きな差が開くことを防げます。

全て全角だった場合に合わせて、省略する文字数を調整すれば、レイアウトが崩れる事は無くなります。

参考情報

https://ref.xaio.jp/ruby/classes/string/bytesize