如何在迭代器上调用count并仍使用迭代器的项?

std*_*std 5 rust

parts.count()导致所有权转移,因此parts不能再使用.

fn split(slice: &[u8], splitter: &[u8]) -> Option<Vec<u8>> {
    let mut parts = slice.split(|b| splitter.contains(b));

    let len = parts.count(); //ownership transfer

    if len >= 2 {
        Some(parts.nth(1).unwrap().to_vec())
    } else if len >= 1 {
        Some(parts.nth(0).unwrap().to_vec())
    } else {
        None
    }
}

fn main() {
    split(&[1u8, 2u8, 3u8], &[2u8]);
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*eev 7

Vec如果您只需要使用第一或第二部分,也可以避免不必要的分配:

fn split<'a>(slice: &'a [u8], splitter: &[u8]) -> Option<&'a [u8]> {
    let mut parts = slice.split(|b| splitter.contains(b)).fuse();

    let first = parts.next();
    let second = parts.next();

    second.or(first)
}
Run Code Online (Sandbox Code Playgroud)

然后,如果您确实需要一个Vec,则可以映射结果:

split(&[1u8, 2u8, 3u8], &[2u8]).map(|s| s.to_vec())
Run Code Online (Sandbox Code Playgroud)

当然,如果你愿意,你可以将to_vec()转换移动到函数中:

second.or(first).map(|s| s.to_vec())
Run Code Online (Sandbox Code Playgroud)

我调用fuse()迭代器是为了保证它None在第一个返回后总是None返回(一般迭代器协议不保证)。


She*_*ter 7

其他答案是回答您的问题的好建议,但我想指出另一个通用解决方案:创建多个迭代器:

fn split(slice: &[u8], splitter: &[u8]) -> Option<Vec<u8>> {
    let mut parts = slice.split(|b| splitter.contains(b));
    let parts2 = slice.split(|b| splitter.contains(b));

    let len = parts2.count();

    if len >= 2 {
        Some(parts.nth(1).unwrap().to_vec())
    } else if len >= 1 {
        Some(parts.nth(0).unwrap().to_vec())
    } else {
        None
    }
}

fn main() {
    split(&[1u8, 2u8, 3u8], &[2u8]);
}
Run Code Online (Sandbox Code Playgroud)

您通常可以创建多个只读迭代器。有些迭代器甚至实现了Clone,所以你可以直接说iter.clone().count()。不幸的是,Split它不是其中之一,因为它拥有传入的闭包。