簡體   English   中英

如何在 Rust 中將字符串拆分為塊以插入空格

[英]How to split string into chunks in Rust to insert spaces

我正在嘗試學習 Rust。 我最近遇到的一個問題如下:給定一個String ,它恰好是 n 的某個倍數,我想將字符串拆分為大小為 n 的塊,並在這些塊之間插入一個空格,然后收集回一個單個字符串。

我遇到的問題是chars()方法返回Chars結構,由於某種原因它沒有實現SliceConcatExt特征,因此無法調用chunks()

此外,一旦我成功創建了一個 Chunks 結構(通過調用.bytes()代替),我不確定如何調用.join(' ')因為元素現在是字節切片的Chunks ......

必須有一種優雅的方式來做到這一點,我錯過了。

例如,這是一個說明情況的輸入/輸出:

given: whatupmyname, 4
output: what upmy name

這是我寫得很糟糕的嘗試:

let n = 4;
let text = "whatupmyname".into_string();
text.chars()
    // compiler error on chunks() call
    .chunks(n)
    .collect::<Vec<String>>()
    .join(' ')

這里的問題是chars()bytes()返回Iterator s,而不是切片。 你可以使用as_bytes() ,它會給你一個&[u8] 但是,您不能直接從&str中獲取&[char] ,因為只存在字節本身,並且char必須通過查看並查看每個字節組成的字節數來創建。 你必須做這樣的事情:

text.chars()
    .collect::<Vec<char>>()
    .chunks(n)
    .map(|c| c.iter().collect::<String>())
    .collect::<Vec<String>>()
    .join(" ");

但是,我不建議這樣做,因為它必須在此過程中為VecString分配大量臨時存儲空間。 相反,你可以做這樣的事情,它只需要分配來創建最終的String

text.chars()
    .enumerate()
    .flat_map(|(i, c)| {
        if i != 0 && i % n == 0 {
            Some(' ')
        } else {
            None
        }
        .into_iter()
        .chain(std::iter::once(c))
    })
    .collect::<String>()

在最后一次收集之前,它一直作為迭代器,通過 flat_mapping 使用一個迭代器,該迭代器要么只是字符,要么是空格,然后是字符。

所以如果你想從一個字符列表中創建一個字符串,你可以使用fold

像這樣的東西:

text.chars
    .enumerate()
    .fold(String::new(), |acc, (i, c)| {
        if i != 0 && i == n {
            format!("{} {}", acc, c)
        } else {
            format!("{}{}", acc, c)
        }
    })

如果要拆分的數據大小是固定的,則:

use std::str;

fn main() {
    let subs = "&#8204;&#8203;&#8204;&#8203;&#8204;&#8203;&#8203;&#8204;&#8203;&#8204;".as_bytes()
        .chunks(7)
        .map(str::from_utf8)
        .collect::<Result<Vec<&str>, _>>()
        .unwrap();
        
    println!("{:?}", subs);
}

// >> ["&#8204;", "&#8203;", "&#8204;", "&#8203;", "&#8204;", "&#8203;", "&#8203;", "&#8204;", "&#8203;", "&#8204;"]

這樣一個簡單的任務可以用一個while循環來解決:

fn main() {
    let n = 4;
    let text = "whatupmyname";
    let mut it = text.chars().enumerate();
    let mut rslt = String::from("");

    while let Some((i, c)) = it.next() {
        rslt.push(c);
        if (i + 1) % n == 0 {
            rslt.push(' ');
        }
    } 
    println!("{}", rslt);  
}

為了完整起見,這里是 Chayim-Friedman 風格的循環(見評論)

    …
    for (i, c) in text.chars().enumerate() {
        rslt.push(c);
        if (i + 1) % n == 0 {
            rslt.push(' ');
        }
    }
    …

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM