Rust的String是否有一种方法可以返回字符数量而不是字节数量?

109

根据 Rust 所述,String::len 方法返回组成字符串的字节数,这可能与字符长度不一致。

例如,如果我们考虑以下日语字符串,则 len() 将返回 30,即字节数,而不是字符数,后者应为 10:

let s = String::from("ラウトは難しいです!");
s.len() // returns 30.
我发现获取字符数量的唯一方法是使用以下函数:
s.chars().count()

上述代码返回10,表示字符数正确。

除了我上面使用的方法,String类中是否有其他返回字符数的方法?


5
请注意,由于 Unicode 的特殊性,“字符数”可能不是您所认为的那样。例如,这个字符串:“é”在 playground 中显示有两个字符:https://play.rust-lang.org/?gist=143ea763c0b16bd4ee12e628fb7ff4ca&version=stable,而这个字符串:“é”只有一个字符:https://play.rust-lang.org/?gist=af950651bb6394e7bc2a966147e1b035&version=stable。 - Jmb
3
请参见 https://crates.io/crates/unicode-segmentation。 - user25064
请参考以下带有字符列表字节表示的示例:Rust Playground - Claudio Fsr
1个回答

116

除了我上面使用的方法外,String 中是否有返回字符数的方法?

没有。使用s.chars().count()是正确的。请注意,这是一个O(N)操作(因为UTF-8很复杂),而获取字节数是一个O(1)操作。

您可以查看 str 中的所有方法

正如评论中指出的那样,char 是一个特定的概念:

重要的是要记住,char 表示Unicode Scalar Value,并且可能与您对“字符”的理解不匹配。迭代图形簇可能是您实际想要的内容。

一个这样的例子是预组合字符:

fn main() {
    println!("{}", "é".chars().count()); // 2
    println!("{}", "é".chars().count()); // 1
}

您可能更喜欢使用来自unicode-segmentation crate的graphemes

use unicode_segmentation::UnicodeSegmentation; // 1.6.0

fn main() {
    println!("{}", "é".graphemes(true).count()); // 1
    println!("{}", "é".graphemes(true).count()); // 1
}

7
顺便说一下,ˋs.chars().count()ˋ 是 Unicode 代码点的数量,你可以使用 unicode-segmentation 来拆分成单个字符。 - Grégory OBANOS
@Shepmaster,感谢您的回答。我知道字符和字符串是不同的,正如您从我的问题中可以猜到的那样。我只是想知道是否有更有效和直观的方法来做到这一点。 - Salvatore Cosentino
@GrégoryOBANOS 谢谢您的评论,但我不打算为应该很简单的事情安装任何东西。 - Salvatore Cosentino
15
直白地说,计算字符串中的字符数量并不简单(参见为什么在Rust中大写字符串的第一个字母如此复杂?),如果您避免使用Rust创建工具箱,将会受到极大的损失。许多程序员错误地认为处理自然语言应该是“简单”的,导致许多程序出错。 Rust正在努力避免这种命运。 - Shepmaster
1
@JerzyBrzóska 我认为您正在遇到如何在打印从stdin读取的字符串时忽略换行符? - Shepmaster
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接