Skip to content

Commit 80c9487

Browse files
committed
Add Itertools::intersperse_with
1 parent 2c6b6ed commit 80c9487

File tree

2 files changed

+100
-2
lines changed

2 files changed

+100
-2
lines changed

src/intersperse.rs

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<I> Iterator for Intersperse<I>
6262
Self: Sized, F: FnMut(B, Self::Item) -> B,
6363
{
6464
let mut accum = init;
65-
65+
6666
if let Some(x) = self.peek.take() {
6767
accum = f(accum, x);
6868
}
@@ -77,3 +77,81 @@ impl<I> Iterator for Intersperse<I>
7777
})
7878
}
7979
}
80+
81+
/// An iterator adaptor to insert a particular value created by a function
82+
/// between each element of the adapted iterator.
83+
///
84+
/// Iterator element type is `I::Item`
85+
///
86+
/// This iterator is *fused*.
87+
///
88+
/// See [`.intersperse_with()`](../trait.Itertools.html#method.intersperse_with) for more information.
89+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
90+
#[derive(Debug)]
91+
pub struct IntersperseWith<I, ElemF>
92+
where I: Iterator,
93+
ElemF: FnMut() -> I::Item,
94+
{
95+
element: ElemF,
96+
iter: Fuse<I>,
97+
peek: Option<I::Item>,
98+
}
99+
100+
/// Create a new IntersperseWith iterator
101+
pub fn intersperse_with<I, ElemF>(iter: I, elt: ElemF) -> IntersperseWith<I, ElemF>
102+
where I: Iterator,
103+
ElemF: FnMut() -> I::Item
104+
{
105+
let mut iter = iter.fuse();
106+
IntersperseWith {
107+
peek: iter.next(),
108+
iter: iter,
109+
element: elt,
110+
}
111+
}
112+
113+
impl<I, ElemF> Iterator for IntersperseWith<I, ElemF>
114+
where I: Iterator,
115+
ElemF: FnMut() -> I::Item
116+
{
117+
type Item = I::Item;
118+
#[inline]
119+
fn next(&mut self) -> Option<I::Item> {
120+
if self.peek.is_some() {
121+
self.peek.take()
122+
} else {
123+
self.peek = self.iter.next();
124+
if self.peek.is_some() {
125+
Some((self.element)())
126+
} else {
127+
None
128+
}
129+
}
130+
}
131+
132+
fn size_hint(&self) -> (usize, Option<usize>) {
133+
// 2 * SH + { 1 or 0 }
134+
let has_peek = self.peek.is_some() as usize;
135+
let sh = self.iter.size_hint();
136+
size_hint::add_scalar(size_hint::add(sh, sh), has_peek)
137+
}
138+
139+
fn fold<B, F>(mut self, init: B, mut f: F) -> B where
140+
Self: Sized, F: FnMut(B, Self::Item) -> B,
141+
{
142+
let mut accum = init;
143+
144+
if let Some(x) = self.peek.take() {
145+
accum = f(accum, x);
146+
}
147+
148+
let element = &mut self.element;
149+
150+
self.iter.fold(accum,
151+
|accum, x| {
152+
let accum = f(accum, (element)());
153+
let accum = f(accum, x);
154+
accum
155+
})
156+
}
157+
}

src/lib.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub mod structs {
107107
pub use crate::format::{Format, FormatWith};
108108
#[cfg(feature = "use_std")]
109109
pub use crate::groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups};
110-
pub use crate::intersperse::Intersperse;
110+
pub use crate::intersperse::{Intersperse, IntersperseWith};
111111
#[cfg(feature = "use_std")]
112112
pub use crate::kmerge_impl::{KMerge, KMergeBy};
113113
pub use crate::merge_join::MergeJoinBy;
@@ -390,6 +390,26 @@ pub trait Itertools : Iterator {
390390
intersperse::intersperse(self, element)
391391
}
392392

393+
/// An iterator adaptor to insert a particular value created by a function
394+
/// between each element of the adapted iterator.
395+
///
396+
/// Iterator element type is `Self::Item`.
397+
///
398+
/// This iterator is *fused*.
399+
///
400+
/// ```
401+
/// use itertools::Itertools;
402+
///
403+
/// let mut i = 10;
404+
/// itertools::assert_equal((0..3).intersperse_with(|| { i -= 1; i }), vec![0, 9, 1, 8, 2]);
405+
/// ```
406+
fn intersperse_with<F>(self, element: F) -> IntersperseWith<Self, F>
407+
where Self: Sized,
408+
F: FnMut() -> Self::Item
409+
{
410+
intersperse::intersperse_with(self, element)
411+
}
412+
393413
/// Create an iterator which iterates over both this and the specified
394414
/// iterator simultaneously, yielding pairs of two optional elements.
395415
///

0 commit comments

Comments
 (0)