rust 如何跳过循环中的最后一个字符串元素?

8fsztsew  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(113)

如何跳过循环中的最后一个字符串元素?
我的解决方案很有效

fn main() {
    let s = "123456".to_string();
    for ch in (&s[..s.len()-1]).chars() { // skip the last element
        println!("{}", ch);
    }
}

字符串
但还有更好的吗?
类似于skip() https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.skip,允许跳过循环中的第一个元素

3gtaxfhh

3gtaxfhh1#

当下一个字符是最后一个字符时,也就是当peek()没有看到另一个字符时,可以使用peekable()停止打印:

let s = "12345ඞ".to_string();
let mut it = s.chars().peekable();
while let Some(ch) = it.next() {
    if it.peek().is_some() {  // skip None
        println!("{ch}");
    }
}

字符串

  • 可以处理Unicode字符。*

Playground

m528fe3b

m528fe3b2#

您可以使用next_back(来自DoubleEndedIterator trait)在开始迭代之前显式删除最后一个字符:

fn main() {
    let s = "123456".to_string();
    let mut chars = s.chars();  // Create mutable iterator
    chars.next_back();          // Discard last element
    for ch in chars {           // Iterate the rest
        println!("{}", ch);
    }
}

字符串
如果需要删除多个字符,只需在一个简单的范围循环中运行next_back(可能会检查None,以便在尝试跳过的字符多于现有字符时立即执行break)。
正如我在评论中提到的,你的解决方案在UTF-8字符存在的情况下是不安全的,因为它可能会在单个UTF-8字符的字节之间进行切片。这个解决方案是安全的,因为next_back将正确解码并省略任何宽度的UTF-8字符。
如果不先从后向前操作,你就不能做这样的事情,原因是可变宽度的UTF-8字符意味着纯粹按向前顺序操作,Rust不知道从字符串末尾到 * 到达 * 字符串末尾的x字符是什么时候(在这一点上,它只能在事后才知道)。即使它知道它距离末尾有4个字节,它也可能是1。(单个四字节字符),2(两个双字节字符),3(两个单字节和一个双字节),或4(四个单)字符在该范围内,它必须解码,以找出它是在哪个场景。只有ExactSizeIterator s,其中知道他们的精确长度提前,通过巧妙地使用revskipa DoubleEndedIterator , which is what .chars() gives you, cannot.

tjjdgumg

tjjdgumg3#

因为字符串上的.len()返回字节数,而不是字符数,所以您的尝试将因多字节字符而失败。
这里有一个建议:推迟印刷。

fn main() {
    let s = "1é2è3ç4•".to_string();
    let mut chars = s.chars();
    if let Some(mut prev) = chars.next() {
        for ch in chars {
            print!("{} ", prev);
            prev = ch;
        }
        println!();
    }
}
/*
1 é 2 è 3 ç 4
*/

字符串

相关问题