@@ -3144,6 +3144,57 @@ pub trait Itertools: Iterator {
3144
3144
self . k_largest_by ( k, k_smallest:: key_to_cmp ( key) )
3145
3145
}
3146
3146
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(v.iter().tail(1), v.iter().last());
3160
+ ///
3161
+ /// assert_equal((0..100).tail(10), 90..100);
3162
+ /// ```
3163
+ ///
3164
+ /// For double ended iterators without side-effects, you might prefer
3165
+ /// `.rev().take(n).rev()` to have a similar result (lazy and non-allocating)
3166
+ /// without consuming the entire iterator.
3167
+ #[ cfg( feature = "use_alloc" ) ]
3168
+ fn tail ( self , n : usize ) -> VecIntoIter < Self :: Item >
3169
+ where
3170
+ Self : Sized ,
3171
+ {
3172
+ match n {
3173
+ 0 => {
3174
+ self . last ( ) ;
3175
+ Vec :: new ( )
3176
+ }
3177
+ 1 => self . last ( ) . into_iter ( ) . collect ( ) ,
3178
+ _ => {
3179
+ let mut iter = self . fuse ( ) ;
3180
+ let mut data: Vec < _ > = iter. by_ref ( ) . take ( n) . collect ( ) ;
3181
+ // Update `data` cyclically.
3182
+ let idx = iter. fold ( 0 , |i, val| {
3183
+ data[ i] = val;
3184
+ if i + 1 == n {
3185
+ 0
3186
+ } else {
3187
+ i + 1
3188
+ }
3189
+ } ) ;
3190
+ // Respect the insertion order.
3191
+ data. rotate_left ( idx) ;
3192
+ data
3193
+ }
3194
+ }
3195
+ . into_iter ( )
3196
+ }
3197
+
3147
3198
/// Collect all iterator elements into one of two
3148
3199
/// partitions. Unlike [`Iterator::partition`], each partition may
3149
3200
/// have a distinct type.
0 commit comments