繁体   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