Skip to content

Commit cd6f902

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 <scottmcm@users.noreply.github.com>
1 parent 4e44168 commit cd6f902

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
@@ -3147,6 +3147,8 @@ pub trait Itertools: Iterator {
31473147
/// assert_equal(v.iter().tail(10), &v);
31483148
///
31493149
/// assert_equal((0..100).tail(10), 90..100);
3150+
///
3151+
/// assert_equal((0..100).filter(|x| x % 3 == 0).tail(10), (72..100).step_by(3));
31503152
/// ```
31513153
///
31523154
/// For double ended iterators without side-effects, you might prefer
@@ -3164,7 +3166,9 @@ pub trait Itertools: Iterator {
31643166
}
31653167
1 => self.last().into_iter().collect(),
31663168
_ => {
3167-
let mut iter = self.fuse();
3169+
// Skip the starting part of the iterator if possible.
3170+
let (low, _) = self.size_hint();
3171+
let mut iter = self.fuse().skip(low.saturating_sub(n));
31683172
let mut data: Vec<_> = iter.by_ref().take(n).collect();
31693173
// Update `data` cyclically.
31703174
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)