Auto merge of #41439 - ivandardi:master, r=BurntSushi
Stabilize step_by by adding it to Iterator (issue #27741) Inspired by itertools' `take()` method. See issue #27741
This commit is contained in:
commit
543691d0eb
@ -0,0 +1,7 @@
|
|||||||
|
# `iterator_step_by`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#27741]
|
||||||
|
|
||||||
|
[#27741]: https://github.com/rust-lang/rust/issues/27741
|
||||||
|
|
||||||
|
------------------------
|
@ -11,7 +11,7 @@
|
|||||||
use cmp::Ordering;
|
use cmp::Ordering;
|
||||||
|
|
||||||
use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse};
|
use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse};
|
||||||
use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile, Rev};
|
use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
|
||||||
use super::{Zip, Sum, Product};
|
use super::{Zip, Sum, Product};
|
||||||
use super::{ChainState, FromIterator, ZipImpl};
|
use super::{ChainState, FromIterator, ZipImpl};
|
||||||
|
|
||||||
@ -258,6 +258,39 @@ fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an iterator starting at the same point, but stepping by
|
||||||
|
/// the given amount at each iteration.
|
||||||
|
///
|
||||||
|
/// Note that it will always return the first element of the range,
|
||||||
|
/// regardless of the step given.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// The method will panic if the given step is `0`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(iterator_step_by)]
|
||||||
|
/// let a = [0, 1, 2, 3, 4, 5];
|
||||||
|
/// let mut iter = a.into_iter().step_by(2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(iter.next(), Some(&0));
|
||||||
|
/// assert_eq!(iter.next(), Some(&2));
|
||||||
|
/// assert_eq!(iter.next(), Some(&4));
|
||||||
|
/// assert_eq!(iter.next(), None);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "iterator_step_by",
|
||||||
|
reason = "unstable replacement of Range::step_by",
|
||||||
|
issue = "27741")]
|
||||||
|
fn step_by(self, step: usize) -> StepBy<Self> where Self: Sized {
|
||||||
|
assert!(step != 0);
|
||||||
|
StepBy{iter: self, step: step - 1, first_take: true}
|
||||||
|
}
|
||||||
|
|
||||||
/// Takes two iterators and creates a new iterator over both in sequence.
|
/// Takes two iterators and creates a new iterator over both in sequence.
|
||||||
///
|
///
|
||||||
/// `chain()` will return a new iterator which will first iterate over
|
/// `chain()` will return a new iterator which will first iterate over
|
||||||
|
@ -313,7 +313,7 @@
|
|||||||
pub use self::range::Step;
|
pub use self::range::Step;
|
||||||
#[unstable(feature = "step_by", reason = "recent addition",
|
#[unstable(feature = "step_by", reason = "recent addition",
|
||||||
issue = "27741")]
|
issue = "27741")]
|
||||||
pub use self::range::StepBy;
|
pub use self::range::StepBy as DeprecatedStepBy;
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::sources::{Repeat, repeat};
|
pub use self::sources::{Repeat, repeat};
|
||||||
@ -520,6 +520,41 @@ fn size_hint(&self) -> (usize, Option<usize>) {
|
|||||||
#[unstable(feature = "fused", issue = "35602")]
|
#[unstable(feature = "fused", issue = "35602")]
|
||||||
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
|
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
|
||||||
|
|
||||||
|
/// An iterator that steps by n elements every iteration.
|
||||||
|
///
|
||||||
|
/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
|
||||||
|
/// its documentation for more.
|
||||||
|
///
|
||||||
|
/// [`step_by`]: trait.Iterator.html#method.step_by
|
||||||
|
/// [`Iterator`]: trait.Iterator.html
|
||||||
|
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||||
|
#[unstable(feature = "iterator_step_by",
|
||||||
|
reason = "unstable replacement of Range::step_by",
|
||||||
|
issue = "27741")]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct StepBy<I> {
|
||||||
|
iter: I,
|
||||||
|
step: usize,
|
||||||
|
first_take: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "iterator_step_by",
|
||||||
|
reason = "unstable replacement of Range::step_by",
|
||||||
|
issue = "27741")]
|
||||||
|
impl<I> Iterator for StepBy<I> where I: Iterator {
|
||||||
|
type Item = I::Item;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.first_take {
|
||||||
|
self.first_take = false;
|
||||||
|
self.iter.next()
|
||||||
|
} else {
|
||||||
|
self.iter.nth(self.step)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An iterator that strings two iterators together.
|
/// An iterator that strings two iterators together.
|
||||||
///
|
///
|
||||||
/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
|
/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
|
||||||
|
@ -144,6 +144,33 @@ fn test_iterator_chain_find() {
|
|||||||
assert_eq!(iter.next(), None);
|
assert_eq!(iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_iterator_step_by() {
|
||||||
|
// Identity
|
||||||
|
// Replace with (0..).step_by(1) after Range::step_by gets removed
|
||||||
|
let mut it = Iterator::step_by((0..), 1).take(3);
|
||||||
|
assert_eq!(it.next(), Some(0));
|
||||||
|
assert_eq!(it.next(), Some(1));
|
||||||
|
assert_eq!(it.next(), Some(2));
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
|
||||||
|
// Replace with (0..).step_by(3) after Range::step_by gets removed
|
||||||
|
let mut it = Iterator::step_by((0..), 3).take(4);
|
||||||
|
assert_eq!(it.next(), Some(0));
|
||||||
|
assert_eq!(it.next(), Some(3));
|
||||||
|
assert_eq!(it.next(), Some(6));
|
||||||
|
assert_eq!(it.next(), Some(9));
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_iterator_step_by_zero() {
|
||||||
|
// Replace with (0..).step_by(0) after Range::step_by gets removed
|
||||||
|
let mut it = Iterator::step_by((0..), 0);
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filter_map() {
|
fn test_filter_map() {
|
||||||
let it = (0..).step_by(1).take(10)
|
let it = (0..).step_by(1).take(10)
|
||||||
@ -1119,4 +1146,4 @@ fn test_step_replace_no_between() {
|
|||||||
let y = x.replace_one();
|
let y = x.replace_one();
|
||||||
assert_eq!(x, 1);
|
assert_eq!(x, 1);
|
||||||
assert_eq!(y, 5);
|
assert_eq!(y, 5);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#![feature(fixed_size_array)]
|
#![feature(fixed_size_array)]
|
||||||
#![feature(flt2dec)]
|
#![feature(flt2dec)]
|
||||||
#![feature(fmt_internals)]
|
#![feature(fmt_internals)]
|
||||||
|
#![feature(iterator_step_by)]
|
||||||
#![feature(i128_type)]
|
#![feature(i128_type)]
|
||||||
#![feature(iter_rfind)]
|
#![feature(iter_rfind)]
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
|
Loading…
Reference in New Issue
Block a user