Search code examples
loopsvectorrustinfinite-loop

Removing adjacent values from vector


I made this function which should remove all adjacent values it finds from a vector.

fn remove_adjacent<T: std::cmp::PartialEq>(values: &mut Vec<T>, item: T) {
    let mut offset = 0;

    while let Some(idx) = values.iter().skip(offset).position(|n| *n == item) {
        let length = values
            .iter()
            .skip(idx)
            .position(|v| *v != item)
            .unwrap_or(values.len() - idx);

        if length > 1 {
            values.drain(idx + 1..length + idx);
        }

        offset = idx + 1;
    }
}

It works fine for vectors like

vec![2, 1, 3, 3, 3, 3, 3];

But not for vectors whose target element to be removed repeats after a non-target value, like

vec![2, 1, 3, 3, 3, 3, 3, 7, 3, 3, 3];

It should also remove the threes 3 values after 7, but instead it get stuck in an infinite loop. I'm not able find the error on my own, if anyone has tips on how to fix this I'll really appreciate it.

Example on Rust Playground


Solution

  • Everything in your code works correctly except getting the idx.

    You can print out the idx and see what is wrong with it. Printing offset helps too.

    fn remove_adjacent<T: std::cmp::PartialEq>(values: &mut Vec<T>, item: T) {
        let mut offset = 0;
    
        while let Some(idx) = values.iter().skip(offset).position(|n| *n == item) {
            dbg!(idx, offset); // prints out nicely
    
            let length = values
                .iter()
                .skip(idx)
                .position(|v| *v != item)
                .unwrap_or(values.len() - idx);
    
            if length > 1 {
                values.drain(idx + 1..length + idx);
            }
    
            offset = idx + 1;
        }
    }
    

    You will notice that the idx is not always what you want.

    This is happening becuase .position( counts not in values but in the iterator you get after .skip(offset).

    I hope looking at the printed values and my clue guides you to fix the error on your own. Good luck! 😃