diff --git a/benches/bench1.rs b/benches/bench1.rs index 0946affe5..b01b8f360 100644 --- a/benches/bench1.rs +++ b/benches/bench1.rs @@ -1,4 +1,4 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; use itertools::free::cloned; use itertools::iproduct; use itertools::Itertools; @@ -648,6 +648,22 @@ fn step_range_10(c: &mut Criterion) { }); } +fn vec_iter_mut_partition(c: &mut Criterion) { + let data = std::iter::repeat(-1024i32..1024) + .take(256) + .flatten() + .collect_vec(); + c.bench_function("vec iter mut partition", move |b| { + b.iter_batched( + || data.clone(), + |mut data| { + black_box(itertools::partition(black_box(&mut data), |n| *n >= 0)); + }, + BatchSize::LargeInput, + ) + }); +} + fn cartesian_product_iterator(c: &mut Criterion) { let xs = vec![0; 16]; @@ -803,6 +819,7 @@ criterion_group!( step_vec_10, step_range_2, step_range_10, + vec_iter_mut_partition, cartesian_product_iterator, multi_cartesian_product_iterator, cartesian_product_nested_for, diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index 3528e3b23..f622bceda 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -901,17 +901,11 @@ where type Item = Result; fn next(&mut self) -> Option { - loop { - match self.iter.next() { - Some(Ok(v)) => { - if (self.f)(&v) { - return Some(Ok(v)); - } - } - Some(Err(e)) => return Some(Err(e)), - None => return None, - } - } + let f = &mut self.f; + self.iter.find(|res| match res { + Ok(t) => f(t), + _ => true, + }) } fn size_hint(&self) -> (usize, Option) { @@ -988,17 +982,11 @@ where type Item = Result; fn next(&mut self) -> Option { - loop { - match self.iter.next() { - Some(Ok(v)) => { - if let Some(v) = (self.f)(v) { - return Some(Ok(v)); - } - } - Some(Err(e)) => return Some(Err(e)), - None => return None, - } - } + let f = &mut self.f; + self.iter.find_map(|res| match res { + Ok(t) => f(t).map(Ok), + Err(e) => Some(Err(e)), + }) } fn size_hint(&self) -> (usize, Option) { diff --git a/src/lib.rs b/src/lib.rs index 9a4043095..f3b6e807d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4054,18 +4054,11 @@ where { let mut split_index = 0; let mut iter = iter.into_iter(); - 'main: while let Some(front) = iter.next() { + while let Some(front) = iter.next() { if !pred(front) { - loop { - match iter.next_back() { - Some(back) => { - if pred(back) { - std::mem::swap(front, back); - break; - } - } - None => break 'main, - } + match iter.rfind(|back| pred(back)) { + Some(back) => std::mem::swap(front, back), + None => break, } } split_index += 1; diff --git a/src/unique_impl.rs b/src/unique_impl.rs index 9b103a075..0f6397e48 100644 --- a/src/unique_impl.rs +++ b/src/unique_impl.rs @@ -61,13 +61,8 @@ where type Item = I::Item; fn next(&mut self) -> Option { - while let Some(v) = self.iter.next() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None + let Self { iter, used, f } = self; + iter.find(|v| used.insert(f(v), ()).is_none()) } #[inline] @@ -89,13 +84,8 @@ where F: FnMut(&I::Item) -> V, { fn next_back(&mut self) -> Option { - while let Some(v) = self.iter.next_back() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None + let Self { iter, used, f } = self; + iter.rfind(|v| used.insert(f(v), ()).is_none()) } } @@ -115,14 +105,15 @@ where type Item = I::Item; fn next(&mut self) -> Option { - while let Some(v) = self.iter.iter.next() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let UniqueBy { iter, used, .. } = &mut self.iter; + iter.find_map(|v| { + if let Entry::Vacant(entry) = used.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); } - } - None + None + }) } #[inline] @@ -142,14 +133,15 @@ where I::Item: Eq + Hash + Clone, { fn next_back(&mut self) -> Option { - while let Some(v) = self.iter.iter.next_back() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let UniqueBy { iter, used, .. } = &mut self.iter; + iter.rev().find_map(|v| { + if let Entry::Vacant(entry) = used.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); } - } - None + None + }) } }