Skip to content

Commit 8fa9b98

Browse files
warren2kmightyiam
authored andcommitted
with_prev
Co-authored-by: Warren Wise <warren.a.wise@gmail.com>
1 parent 37bd72a commit 8fa9b98

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ pub mod structs {
147147
#[cfg(feature = "use_std")]
148148
pub use crate::unique_impl::{Unique, UniqueBy};
149149
pub use crate::with_position::WithPosition;
150+
pub use crate::with_prev::WithPrev;
150151
pub use crate::zip_eq_impl::ZipEq;
151152
pub use crate::zip_longest::ZipLongest;
152153
pub use crate::ziptuple::Zip;
@@ -243,6 +244,7 @@ mod tuple_impl;
243244
mod unique_impl;
244245
mod unziptuple;
245246
mod with_position;
247+
mod with_prev;
246248
mod zip_eq_impl;
247249
mod zip_longest;
248250
mod ziptuple;
@@ -2247,6 +2249,26 @@ pub trait Itertools: Iterator {
22472249
with_position::with_position(self)
22482250
}
22492251

2252+
/// Return an iterator adaptor that combines each element except the first with
2253+
/// a clone of the previous.
2254+
///
2255+
/// ```
2256+
/// use itertools::Itertools;
2257+
///
2258+
/// let it = (0..4).with_prev();
2259+
/// itertools::assert_equal(it,
2260+
/// vec![(None, 0),
2261+
/// (Some(0), 1),
2262+
/// (Some(1), 2),
2263+
/// (Some(2), 3)]);
2264+
/// ```
2265+
fn with_prev(self) -> WithPrev<Self>
2266+
where
2267+
Self: Sized,
2268+
{
2269+
with_prev::with_prev(self)
2270+
}
2271+
22502272
/// Return an iterator adaptor that yields the indices of all elements
22512273
/// satisfying a predicate, counted from the start of the iterator.
22522274
///

src/with_prev.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use std::fmt;
2+
3+
/// An iterator adaptor that combines each element except the first with a clone of the previous.
4+
///
5+
/// See [`.with_prev()`](crate::Itertools::with_prev) for more information.
6+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
7+
pub struct WithPrev<I>
8+
where
9+
I: Iterator,
10+
{
11+
iter: I,
12+
prev: Option<I::Item>,
13+
}
14+
15+
impl<I> fmt::Debug for WithPrev<I>
16+
where
17+
I: Iterator + fmt::Debug,
18+
I::Item: fmt::Debug,
19+
{
20+
debug_fmt_fields!(WithPrev, prev, iter);
21+
}
22+
23+
impl<I> Clone for WithPrev<I>
24+
where
25+
I: Clone + Iterator,
26+
I::Item: Clone,
27+
{
28+
clone_fields!(iter, prev);
29+
}
30+
31+
/// Create a new `WithPrev` iterator.
32+
pub fn with_prev<I>(iter: I) -> WithPrev<I>
33+
where
34+
I: Iterator,
35+
{
36+
WithPrev { iter, prev: None }
37+
}
38+
39+
impl<I> Iterator for WithPrev<I>
40+
where
41+
I: Iterator,
42+
I::Item: Clone,
43+
{
44+
type Item = (Option<I::Item>, I::Item);
45+
46+
fn next(&mut self) -> Option<Self::Item> {
47+
let next = self.iter.next()?;
48+
let prev = self.prev.replace(next.clone());
49+
Some((prev, next))
50+
}
51+
}

0 commit comments

Comments
 (0)