@@ -3144,6 +3144,55 @@ pub trait Itertools: Iterator {
31443144 self . k_largest_by ( k, k_smallest:: key_to_cmp ( key) )
31453145 }
31463146
3147+ /// Consumes the iterator and return an iterator of the last `n` elements.
3148+ ///
3149+ /// The iterator, if directly collected to a `Vec`, is converted
3150+ /// without any extra copying or allocation cost.
3151+ ///
3152+ /// ```
3153+ /// use itertools::{assert_equal, Itertools};
3154+ ///
3155+ /// let v = vec![5, 9, 8, 4, 2, 12, 0];
3156+ /// assert_equal(v.iter().tail(3), &[2, 12, 0]);
3157+ /// assert_equal(v.iter().tail(10), &v);
3158+ ///
3159+ /// assert_equal((0..100).tail(10), 90..100);
3160+ /// ```
3161+ ///
3162+ /// For double ended iterators without side-effects, you might prefer
3163+ /// `.rev().take(n).rev()` to have a similar result (lazy and non-allocating)
3164+ /// without consuming the entire iterator.
3165+ #[ cfg( feature = "use_alloc" ) ]
3166+ fn tail ( self , n : usize ) -> VecIntoIter < Self :: Item >
3167+ where
3168+ Self : Sized ,
3169+ {
3170+ match n {
3171+ 0 => {
3172+ self . last ( ) ;
3173+ Vec :: new ( )
3174+ }
3175+ 1 => self . last ( ) . into_iter ( ) . collect ( ) ,
3176+ _ => {
3177+ let mut iter = self . fuse ( ) ;
3178+ let mut data: Vec < _ > = iter. by_ref ( ) . take ( n) . collect ( ) ;
3179+ // Update `data` cyclically.
3180+ let idx = iter. fold ( 0 , |i, val| {
3181+ data[ i] = val;
3182+ if i + 1 == n {
3183+ 0
3184+ } else {
3185+ i + 1
3186+ }
3187+ } ) ;
3188+ // Respect the insertion order.
3189+ data. rotate_left ( idx) ;
3190+ data
3191+ }
3192+ }
3193+ . into_iter ( )
3194+ }
3195+
31473196 /// Collect all iterator elements into one of two
31483197 /// partitions. Unlike [`Iterator::partition`], each partition may
31493198 /// have a distinct type.
0 commit comments