std: Implement .rposition() on double-ended iterators with known size

This is a generalization of the vector .rposition() method, to all
double-ended iterators that have the ExactSizeHint trait.

This resolves the slight asymmetry around `position` and `rposition`

* position from front is `vec.iter().position()`
* position from the back was, `vec.rposition()` is now `vec.iter().rposition()`

Additionally, other indexed sequences (only `extra::ringbuf` I think),
will have the same method available once it implements ExactSizeHint.
This commit is contained in:
blake2-ppc 2013-08-30 20:00:14 +02:00
parent e7955b2a7d
commit db22f2627d
4 changed files with 38 additions and 37 deletions

View File

@ -525,7 +525,7 @@ impl BigUint {
#[inline]
pub fn new(v: ~[BigDigit]) -> BigUint {
// omit trailing zeros
let new_len = v.rposition(|n| *n != 0).map_move_default(0, |p| p + 1);
let new_len = v.iter().rposition(|n| *n != 0).map_move_default(0, |p| p + 1);
if new_len == v.len() { return BigUint { data: v }; }
let mut v = v;

View File

@ -18,7 +18,7 @@ implementing the `Iterator` trait.
*/
use cmp;
use num::{Zero, One, Integer, CheckedAdd, Saturating};
use num::{Zero, One, Integer, CheckedAdd, CheckedSub, Saturating};
use option::{Option, Some, None};
use ops::{Add, Mul, Sub};
use cmp::Ord;
@ -604,6 +604,37 @@ impl<'self, A, T: DoubleEndedIterator<&'self mut A>> MutableDoubleEndedIterator
}
}
/// A double-ended iterator with known size
pub trait ExactSizeDoubleEndedIterator<A> {
/// Return the index of the last element satisfying the specified predicate
///
/// If no element matches, None is returned.
#[inline]
fn rposition(&mut self, predicate: &fn(A) -> bool) -> Option<uint>;
}
impl<A, T: DoubleEndedIterator<A> + ExactSizeHint> ExactSizeDoubleEndedIterator<A> for T {
fn rposition(&mut self, predicate: &fn(A) -> bool) -> Option<uint> {
let (size, _) = self.size_hint();
let mut i = size;
loop {
match self.next_back() {
None => break,
Some(x) => {
i = match i.checked_sub(&1) {
Some(x) => x,
None => fail!("rposition: incorrect ExactSizeHint")
};
if predicate(x) {
return Some(i)
}
}
}
}
None
}
}
/// An object implementing random access indexing by `uint`
///
/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.

View File

@ -52,7 +52,7 @@ pub use hash::Hash;
pub use num::Times;
pub use iterator::{FromIterator, Extendable};
pub use iterator::{Iterator, DoubleEndedIterator, RandomAccessIterator, ClonableIterator};
pub use iterator::{OrdIterator, MutableDoubleEndedIterator};
pub use iterator::{OrdIterator, MutableDoubleEndedIterator, ExactSizeDoubleEndedIterator};
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
pub use num::{Orderable, Signed, Unsigned, Round};
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};

View File

@ -274,7 +274,7 @@ impl<'self, T> Iterator<&'self [T]> for RSplitIterator<'self, T> {
return Some(self.v);
}
match self.v.rposition(|x| (self.pred)(x)) {
match self.v.iter().rposition(|x| (self.pred)(x)) {
None => {
self.finished = true;
Some(self.v)
@ -832,7 +832,6 @@ pub trait ImmutableVector<'self, T> {
fn initn(&self, n: uint) -> &'self [T];
fn last(&self) -> &'self T;
fn last_opt(&self) -> Option<&'self T>;
fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U];
unsafe fn unsafe_ref(&self, index: uint) -> *T;
@ -1048,21 +1047,6 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
}
/**
* Find the last index matching some predicate
*
* Apply function `f` to each element of `v` in reverse order. When
* function `f` returns true then an option containing the index is
* returned. If `f` matches no elements then None is returned.
*/
#[inline]
fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
for (i, t) in self.rev_iter().enumerate() {
if f(t) { return Some(self.len() - i - 1); }
}
None
}
/**
* Apply a function to each element of a vector and return a concatenation
* of each result vector
@ -1145,7 +1129,7 @@ impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] {
/// Find the last index containing a matching value
#[inline]
fn rposition_elem(&self, t: &T) -> Option<uint> {
self.rposition(|x| *x == *t)
self.iter().rposition(|x| *x == *t)
}
/// Return true if a vector contains an element with the given value
@ -2932,8 +2916,8 @@ mod tests {
fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
assert_eq!(v.rposition(f), Some(3u));
assert!(v.rposition(g).is_none());
assert_eq!(v.iter().rposition(f), Some(3u));
assert!(v.iter().rposition(g).is_none());
}
#[test]
@ -3215,20 +3199,6 @@ mod tests {
};
}
#[test]
#[should_fail]
fn test_rposition_fail() {
let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
let mut i = 0;
do v.rposition |_elt| {
if i == 2 {
fail!()
}
i += 1;
false
};
}
#[test]
#[should_fail]
fn test_permute_fail() {