What is the idiomatic way to pop the last N elements in a mutable Vec?

后端 未结 3 1257
清歌不尽
清歌不尽 2021-01-17 11:42

I am contributing Rust code to RosettaCode to both learn Rust and contribute to the Rust community at the same time. What is the best idiomatic way to pop the last n

相关标签:
3条回答
  • 2021-01-17 12:42

    I'd recommend using Vec::truncate:

    fn main() {
        let mut nums = vec![1, 2, 3, 4, 5];
    
        let n = 2;
        let final_length = nums.len().saturating_sub(n);
        nums.truncate(final_length);
    
        println!("{:?}", nums);
    }
    

    Additionally, I

    • used saturating_sub to handle the case where there aren't N elements in the vector
    • used vec![] to construct the vector of numbers easily
    • printed out the entire vector in one go

    Normally when you "pop" something, you want to have those values. If you want the values in another vector, you can use Vec::split_off:

    let tail = nums.split_off(final_length);
    

    If you want access to the elements but do not want to create a whole new vector, you can use Vec::drain:

    for i in nums.drain(final_length..) {
        println!("{}", i)
    }
    
    0 讨论(0)
  • 2021-01-17 12:42

    You should take a look at the Vec::truncate function from the standard library, that can do this for you.

    (playground)

    fn main() {
        let mut nums: Vec<u32> = Vec::new();
        nums.push(1);
        nums.push(2);
        nums.push(3);
        nums.push(4);
        nums.push(5);
    
        let n = 2;
        let new_len = nums.len() - n;
        nums.truncate(new_len);
    
        for e in nums {
            println!("{}", e)
        }
    }
    
    0 讨论(0)
  • 2021-01-17 12:44

    An alternate approach would be to use Vec::drain instead. This gives you an iterator so you can actually use the elements that are removed.

    fn main() {
        let mut nums: Vec<u32> = Vec::new();
        nums.push(1);
        nums.push(2);
        nums.push(3);
        nums.push(4);
        nums.push(5);
    
        let n = 2;
        let new_len = nums.len() - n;
    
        for removed_element in nums.drain(new_len..) {
            println!("removed: {}", removed_element);
        }
    
        for retained_element in nums {
            println!("retained: {}", retained_element);
        }
    }
    

    The drain method accepts a RangeArgument in the form of <start-inclusive>..<end-exclusive>. Both start and end may be omitted to default to the beginning/end of the vector. So above, we're really just saying start at new_len and drain to the end.

    0 讨论(0)
提交回复
热议问题