How to efficiently split a Vec<u8> into Vec<Vec<u8>> and sort?

Hi,

I am looking for a fast, memory efficient, solution to split Vec based on value (33u8) into a 2D Vec<Vec> -> sort 2D Vec and flatten it back into Vec. Currently I am doing it in the following way:

fn main() {
    let a = "this is my! vector that ! needs to be sorted!and retured as flat 1D Vec<u8>";
    let mut a_vec = a.as_bytes().to_owned();

    let mut sort: Vec<Vec<u8>> = vec![vec![0u8; 33]; 4]; // Numbers are being calculated in a real case
    let mut j = 0;
    let mut l = 0;
    for i in a_vec.into_iter() {
        if i == 33 {
            sort[j].resize(l, 0x00);
            j = j + 1;
            l = 0;
            continue;
        }
        sort[j][l] = i;
        l = l + 1;
    }
    sort[j].resize(l, 0x00);
    sort.sort();

    for i in sort.iter() {
        println!("{:?}", String::from_utf8(i.to_vec()).unwrap());
    }

// using for loop to merge it back together
}

is there a better way?

How about this?

fn main() {
    let a = "this is my! vector that ! needs to be sorted!and retured as flat 1D Vec<u8>";
    let mut a_vec = a.as_bytes().to_owned();

    let mut sort: Vec<_> = a_vec.split(|i| *i == 33).collect();
    sort.sort();

    for i in sort.iter() {
        println!("{:?}", String::from_utf8(i.to_vec()).unwrap());
    }
    
    let concat: Vec<u8> = sort.join(&33);
    println!("{}", String::from_utf8(concat).unwrap());
}
2 Likes
let sort = {
    let mut a_elems = a.as_bytes().iter().copied();
    let mut sort = vec![];
    loop {
        let mut v: Vec<u8> = a_elems.by_ref().take_while(|&x| x != 33).collect();
        if v.is_empty() { break; }
        sort.push(v);
    }
    sort
};

EDIT: actually I had forgotten about .split(), that's more idiomatic :sweat_smile:, so go for @alice's solution (except for the to_owned() call, which should not be necessary).

1 Like