Skip to content

Commit db22f26

Browse files
author
blake2-ppc
committed
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.
1 parent e7955b2 commit db22f26

File tree

4 files changed

+38
-37
lines changed

4 files changed

+38
-37
lines changed

src/libextra/num/bigint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ impl BigUint {
525525
#[inline]
526526
pub fn new(v: ~[BigDigit]) -> BigUint {
527527
// omit trailing zeros
528-
let new_len = v.rposition(|n| *n != 0).map_move_default(0, |p| p + 1);
528+
let new_len = v.iter().rposition(|n| *n != 0).map_move_default(0, |p| p + 1);
529529

530530
if new_len == v.len() { return BigUint { data: v }; }
531531
let mut v = v;

src/libstd/iterator.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ implementing the `Iterator` trait.
1818
*/
1919

2020
use cmp;
21-
use num::{Zero, One, Integer, CheckedAdd, Saturating};
21+
use num::{Zero, One, Integer, CheckedAdd, CheckedSub, Saturating};
2222
use option::{Option, Some, None};
2323
use ops::{Add, Mul, Sub};
2424
use cmp::Ord;
@@ -604,6 +604,37 @@ impl<'self, A, T: DoubleEndedIterator<&'self mut A>> MutableDoubleEndedIterator
604604
}
605605
}
606606

607+
/// A double-ended iterator with known size
608+
pub trait ExactSizeDoubleEndedIterator<A> {
609+
/// Return the index of the last element satisfying the specified predicate
610+
///
611+
/// If no element matches, None is returned.
612+
#[inline]
613+
fn rposition(&mut self, predicate: &fn(A) -> bool) -> Option<uint>;
614+
}
615+
616+
impl<A, T: DoubleEndedIterator<A> + ExactSizeHint> ExactSizeDoubleEndedIterator<A> for T {
617+
fn rposition(&mut self, predicate: &fn(A) -> bool) -> Option<uint> {
618+
let (size, _) = self.size_hint();
619+
let mut i = size;
620+
loop {
621+
match self.next_back() {
622+
None => break,
623+
Some(x) => {
624+
i = match i.checked_sub(&1) {
625+
Some(x) => x,
626+
None => fail!("rposition: incorrect ExactSizeHint")
627+
};
628+
if predicate(x) {
629+
return Some(i)
630+
}
631+
}
632+
}
633+
}
634+
None
635+
}
636+
}
637+
607638
/// An object implementing random access indexing by `uint`
608639
///
609640
/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.

src/libstd/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub use hash::Hash;
5252
pub use num::Times;
5353
pub use iterator::{FromIterator, Extendable};
5454
pub use iterator::{Iterator, DoubleEndedIterator, RandomAccessIterator, ClonableIterator};
55-
pub use iterator::{OrdIterator, MutableDoubleEndedIterator};
55+
pub use iterator::{OrdIterator, MutableDoubleEndedIterator, ExactSizeDoubleEndedIterator};
5656
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
5757
pub use num::{Orderable, Signed, Unsigned, Round};
5858
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};

src/libstd/vec.rs

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ impl<'self, T> Iterator<&'self [T]> for RSplitIterator<'self, T> {
274274
return Some(self.v);
275275
}
276276

277-
match self.v.rposition(|x| (self.pred)(x)) {
277+
match self.v.iter().rposition(|x| (self.pred)(x)) {
278278
None => {
279279
self.finished = true;
280280
Some(self.v)
@@ -832,7 +832,6 @@ pub trait ImmutableVector<'self, T> {
832832
fn initn(&self, n: uint) -> &'self [T];
833833
fn last(&self) -> &'self T;
834834
fn last_opt(&self) -> Option<&'self T>;
835-
fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
836835
fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U];
837836
unsafe fn unsafe_ref(&self, index: uint) -> *T;
838837

@@ -1048,21 +1047,6 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
10481047
if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
10491048
}
10501049

1051-
/**
1052-
* Find the last index matching some predicate
1053-
*
1054-
* Apply function `f` to each element of `v` in reverse order. When
1055-
* function `f` returns true then an option containing the index is
1056-
* returned. If `f` matches no elements then None is returned.
1057-
*/
1058-
#[inline]
1059-
fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
1060-
for (i, t) in self.rev_iter().enumerate() {
1061-
if f(t) { return Some(self.len() - i - 1); }
1062-
}
1063-
None
1064-
}
1065-
10661050
/**
10671051
* Apply a function to each element of a vector and return a concatenation
10681052
* of each result vector
@@ -1145,7 +1129,7 @@ impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] {
11451129
/// Find the last index containing a matching value
11461130
#[inline]
11471131
fn rposition_elem(&self, t: &T) -> Option<uint> {
1148-
self.rposition(|x| *x == *t)
1132+
self.iter().rposition(|x| *x == *t)
11491133
}
11501134

11511135
/// Return true if a vector contains an element with the given value
@@ -2932,8 +2916,8 @@ mod tests {
29322916
fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
29332917
let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
29342918

2935-
assert_eq!(v.rposition(f), Some(3u));
2936-
assert!(v.rposition(g).is_none());
2919+
assert_eq!(v.iter().rposition(f), Some(3u));
2920+
assert!(v.iter().rposition(g).is_none());
29372921
}
29382922

29392923
#[test]
@@ -3215,20 +3199,6 @@ mod tests {
32153199
};
32163200
}
32173201

3218-
#[test]
3219-
#[should_fail]
3220-
fn test_rposition_fail() {
3221-
let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
3222-
let mut i = 0;
3223-
do v.rposition |_elt| {
3224-
if i == 2 {
3225-
fail!()
3226-
}
3227-
i += 1;
3228-
false
3229-
};
3230-
}
3231-
32323202
#[test]
32333203
#[should_fail]
32343204
fn test_permute_fail() {

0 commit comments

Comments
 (0)