Hi Guys,
I am wondering what is the most efficient or idiomatic way to drop a range of elements from the front of a VecDeque and keep the last N elements?
I see that truncate() drops elements nice and cleanly from the back but what is the equivalent to doing this at the front?
It looks like I could use drain(), split_off() or retain().
From reading the documentation drain involves some iteration and yields the removed items (I want to discard these).
Retain looks useful for "cherry-picking" which elements to keep that might not be contiguous in memory.
Since I am not aware of any equivalent to truncate for removing a range of elements from the front, I suspect that split_off() might be the most efficient way to do this?
I'll experiment with the various methods but perhaps someone in will have a definitive, best known answer.
@matklad's answer is the right option for now, but consider opening a PR to add truncate_front and seeing what the libs team has to say. It seems to me like a plausible thing to have.
Thanks for the replies guys. I have been away from my PC for the past few days but had a few mins to do a quick test today to compare the split_off() method verses the drop/drain method.
I am not sure how accurate the test below is but from repeated testing, the split_off() method was about 23 times faster to drop half of the 100 million values compared to the drop/drain method. On my PC the split_off() method completed the task in 270ms compared to 6300ms for the drop/drain method.
Again, I am not too sure how scientific this test is and haven't tested it with different values such as strings etc. but for now I'll be happy to use the split_off() method to truncate the front of a vec deque.
Thanks for your inputs.
djme.
use std::collections::VecDeque;
use std::time;
fn main() {
let mut vd = VecDeque::new();
let max_num = 100_000_000;
let keep_last_n = max_num / 2 ;
//populate vec deque
vd.extend(0..max_num);
println!("vec deque initialized. Size is {}", vd.len());
//take starting time
let now = time::Instant::now();
//Method 1: keep the last n elements - split method
vd = vd.split_off(vd.len() - keep_last_n);
//Method 2: keep the last n elements - drop/drain
//drop(vd.drain(0..keep_last_n));
println!("Done in {} milliseconds", now.elapsed().as_millis());
println!("{:?}", vd.len());
}
Thanks matklad/All,
The drain method does seem like the best method to truncate the front of a deque. This was not the case when I had completed some initial testing (in debug mode) but, as recommended by scottmcm, I retested with --release and using drain was indeed much quicker.
PS. Apologies for the delay in reply...I have not had much of a chance to do any Rust programming recently!
Regards,
djme.