Skip to content

Commit 5e41c5a

Browse files
Itertools::tail: skip the starting part of the iterator
If the iterator is exact sized, then `.collect()` finishes the work. More generally, if the size hint knows enough and `nth` is efficient, this might skip most of the iterator efficiently. In the tests, `.filter(..)` is there to ensure that `tail` can't leverage a precise `size_hint` to entirely skip the iteration after initial `.collect()`. Co-Authored-By: scottmcm <[email protected]>
1 parent 0d4930e commit 5e41c5a

File tree

2 files changed

+8
-2
lines changed

2 files changed

+8
-2
lines changed

src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3159,6 +3159,8 @@ pub trait Itertools: Iterator {
31593159
/// assert_equal(v.iter().tail(1), v.iter().last());
31603160
///
31613161
/// assert_equal((0..100).tail(10), 90..100);
3162+
///
3163+
/// assert_equal((0..100).filter(|x| x % 3 == 0).tail(10), (72..100).step_by(3));
31623164
/// ```
31633165
///
31643166
/// For double ended iterators without side-effects, you might prefer
@@ -3176,7 +3178,9 @@ pub trait Itertools: Iterator {
31763178
}
31773179
1 => self.last().into_iter().collect(),
31783180
_ => {
3179-
let mut iter = self.fuse();
3181+
// Skip the starting part of the iterator if possible.
3182+
let (low, _) = self.size_hint();
3183+
let mut iter = self.fuse().skip(low.saturating_sub(n));
31803184
let mut data: Vec<_> = iter.by_ref().take(n).collect();
31813185
// Update `data` cyclically.
31823186
let idx = iter.fold(0, |i, val| {

tests/quick.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,8 @@ quickcheck! {
19521952

19531953
fn tail(v: Vec<i32>, n: u8) -> bool {
19541954
let n = n as usize;
1955-
itertools::equal(v.iter().tail(n), &v[v.len().saturating_sub(n)..])
1955+
let result = &v[v.len().saturating_sub(n)..];
1956+
itertools::equal(v.iter().tail(n), result)
1957+
&& itertools::equal(v.iter().filter(|_| true).tail(n), result)
19561958
}
19571959
}

0 commit comments

Comments
 (0)