How to call a counter on an iterator and still use iterator elements?

parts.count()leads to the transfer of ownership, so partscan no longer be used.

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]);
}
+4
source share
3 answers

You can also avoid unnecessary distributions Vecif you need to use only the first or second part:

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

Then, if you really need to Vec, you can match the result:

split(&[1u8, 2u8, 3u8], &[2u8]).map(|s| s.to_vec())

Of course, if you want, you can move the conversion to_vec()to a function:

second.or(first).map(|s| s.to_vec())

I call fuse()on the iterator to ensure that it will always return Noneafter the first None(which is not guaranteed by the general iterator protocol).

+4

, , collect Vec, :

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

    let len = parts.len();

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

Other answers are good suggestions for answering your problem, but I would like to point out another general solution: create multiple iterators:

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

You can usually create multiple read-only iterators. Some iterators even implement Clone, so you can just say iter.clone().count(). Unfortunately, Splitit is not one of them, because it owns a closed closure.

+1
source

All Articles