rs.nkmk.me

Rustで文字列の長さ(文字数)を取得

Posted: | Tags: Rust, 文字列

Rustで文字列(&str, String)の長さ(文字数)を取得するには、charscountを使う。書記素クラスタも考慮するには、unicode-segmentationを使う。lenはバイト数を返すのでマルチバイト文字が含まれていると文字数と一致しない。

以下のサンプルコードでは、説明のため、型推論によって省略できるときも明示的に型注釈を記述している場合がある。また、例として文字列&strを使うが、文字列Stringでも同じメソッドが使用可能。

文字列のバイト数を取得: len()

lenメソッドが返すのは文字数ではなくバイト数。

文字列が1バイト文字(ASCII文字)のみで構成されていれば、バイト数と文字数は等しい。

let s: &str = "abc<123>";
assert_eq!(s.len(), 8);
source: str_count.rs

しかし、日本語や絵文字などのマルチバイト文字を含む場合、バイト数と文字数は一致しない。例えば、絵文字😀と👍は4バイトなので、「abc😀👍」は11バイトになる。

let s: &str = "abc😀👍";
assert_eq!(s.len(), 11);
source: str_count.rs

文字列の文字数を取得: chars().count()

マルチバイト文字を含む文字列の文字数を取得するには、charsで文字charのイテレータを生成し、countでその数を取得する。

let s: &str = "abc😀👍";
assert_eq!(s.chars().count(), 5);
source: str_count.rs

書記素クラスタを考慮: 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);
source: str_count.rs

書記素クラスタを考慮するにはunicode-segmentationを使う。

UnicodeSegmentationトレイトをインポートすると、&strStringから書記素のイテレータを返すgraphemesメソッドが使えるようになる。

use unicode_segmentation::UnicodeSegmentation;
source: str_count.rs
let s: &str = "🇯🇵";
assert_eq!(s.graphemes(true).count(), 1);

let s: &str = "🇯🇵JPN😀👍";
assert_eq!(s.graphemes(true).count(), 6);
source: str_count.rs

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

関連カテゴリー

関連記事