Rustで文字列の長さ(文字数)を取得
Rustで文字列(&str
, String
)の長さ(文字数)を取得するには、chars
とcount
を使う。書記素クラスタも考慮するには、unicode-segmentationを使う。len
はバイト数を返すのでマルチバイト文字が含まれていると文字数と一致しない。
以下のサンプルコードでは、説明のため、型推論によって省略できるときも明示的に型注釈を記述している場合がある。また、例として文字列&str
を使うが、文字列String
でも同じメソッドが使用可能。
文字列のバイト数を取得: len()
len
メソッドが返すのは文字数ではなくバイト数。
文字列が1バイト文字(ASCII文字)のみで構成されていれば、バイト数と文字数は等しい。
let s: &str = "abc<123>";
assert_eq!(s.len(), 8);
しかし、日本語や絵文字などのマルチバイト文字を含む場合、バイト数と文字数は一致しない。例えば、絵文字😀と👍は4バイトなので、「abc😀👍」は11バイトになる。
let s: &str = "abc😀👍";
assert_eq!(s.len(), 11);
文字列の文字数を取得: chars().count()
マルチバイト文字を含む文字列の文字数を取得するには、chars
で文字char
のイテレータを生成し、count
でその数を取得する。
let s: &str = "abc😀👍";
assert_eq!(s.chars().count(), 5);
書記素クラスタを考慮: unicode-segmentation
char
は書記素クラスタを考慮しないため、chars
では国旗の絵文字などが2文字に分割されてしまう。
It’s important to remember that
char
represents a Unicode Scalar Value, and might not match your idea of what a ‘character’ is. Iteration over grapheme clusters may be what you actually want. str::chars - Rust
count
で2文字としてカウントされる。
let s: &str = "🇯🇵";
assert_eq!(s.chars().count(), 2);
書記素クラスタを考慮するにはunicode-segmentationを使う。
UnicodeSegmentation
トレイトをインポートすると、&str
やString
から書記素のイテレータを返すgraphemes
メソッドが使えるようになる。
use unicode_segmentation::UnicodeSegmentation;
let s: &str = "🇯🇵";
assert_eq!(s.graphemes(true).count(), 1);
let s: &str = "🇯🇵JPN😀👍";
assert_eq!(s.graphemes(true).count(), 6);
graphemes
メソッドのis_extended
引数はtrue
にすることが推奨されている。
If is_extended is true, the iterator is over the extended grapheme clusters; otherwise, the iterator is over the legacy grapheme clusters. UAX#29 recommends extended grapheme cluster boundaries for general processing. unicode_segmentation::UnicodeSegmentation::graphemes - Rust