string - 如何将字符串截断为最多 N 个字符?

标签 string unicode rust truncate

String.truncate(usize) 的预期方法失败是因为它不考虑 Unicode 字符(考虑到 Rust 将字符串视为 Unicode,这令人困惑)。

let mut s = "ボルテックス".to_string();
s.truncate(4);

thread '' panicked at 'assertion failed: self.is_char_boundary(new_len)'

此外,truncate 会修改原始字符串,这并不总是需要的。

我想出的最好办法是转换为 char 并收集到 String

fn truncate(s: String, max_width: usize) -> String {
    s.chars().take(max_width).collect()
}

例如

fn main() {
    assert_eq!(truncate("ボルテックス".to_string(), 0), "");
    assert_eq!(truncate("ボルテックス".to_string(), 4), "ボルテッ");
    assert_eq!(truncate("ボルテックス".to_string(), 100), "ボルテックス");
    assert_eq!(truncate("hello".to_string(), 4), "hell");
}

然而,这感觉非常沉重。

最佳答案

确保您阅读并理解delnan's point :

Unicode is freaking complicated. Are you sure you want char (which corresponds to code points) as unit and not grapheme clusters?

此答案的其余部分假设您有充分的理由使用 char 而不是字素

which is baffling considering Rust treats strings as Unicode

这是不正确的; Rust 将字符串视为 UTF-8。在 UTF-8 中,每个代码点都映射到可变数量的字节。没有将“6 个字符”转换为“N 个字节”的 O(1) 算法,因此标准库不会向您隐藏这一点。

您可以使用 char_indices 逐个字符地遍历字符串并获取该字符的字节索引:

fn truncate(s: &str, max_chars: usize) -> &str {
    match s.char_indices().nth(max_chars) {
        None => s,
        Some((idx, _)) => &s[..idx],
    }
}

fn main() {
    assert_eq!(truncate("ボルテックス", 0), "");
    assert_eq!(truncate("ボルテックス", 4), "ボルテッ");
    assert_eq!(truncate("ボルテックス", 100), "ボルテックス");
    assert_eq!(truncate("hello", 4), "hell");
}

这也会返回一个切片,如果需要,您可以选择将其移入新分配,或者就地改变 String:

// May not be as efficient as inlining the code...
fn truncate_in_place(s: &mut String, max_chars: usize) {
    let bytes = truncate(&s, max_chars).len();
    s.truncate(bytes);
}

fn main() {
    let mut s = "ボルテックス".to_string();
    truncate_in_place(&mut s, 0);
    assert_eq!(s, "");
}

关于string - 如何将字符串截断为最多 N 个字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38461429/

相关文章:

list - 在 self 上指定生命周期时,Rust 在 trait 上使用动态多态性的问题

c++ - 在通过 native 字符串创建 BSTR(使用 _bstr_t 包装器)时,如何设置长度?

c# - 如何将一个句子拆分成字母并在 C# 中存储为字符串数组?

c++ - C++ 的基本自定义字符串类

php - PHP 中的西里尔音译

rust - 如果封装在互斥体中,有状态 Axum 中间件将无法编译

php - 将数组中所有字符串的所有点分隔子字符串填充为相同长度

qt - 在实例化 QApplication 后 qDebug() 时,我丢失了 “unicodeness”

java - 非 ASCII 字符在 JFrame 或任何 Swing 组件中无法正确显示

rust - 如何将 Rust 闭包转换为 C 风格的回调?