How can I truncate a string to have no more than N characters?

The expected approach String.truncate(usize)fails because it does not consider Unicode characters (which is perplexing given that Rust treats strings as Unicode).

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

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

It also truncatemodifies the original string, which is not always desirable.

The best I have come up with is convert to charand collect at String.

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

eg.

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");
}

However, it is very difficult.

+4
source share
1 answer

Make sure you read and understand delnan point :

. , char ( ) , ?

, char, .

, , Rust Unicode

; Rust UTF-8. UTF-8 . O(1) "6 " "N ", .

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, "");
}
+11

Source: https://habr.com/ru/post/1648395/


All Articles