Skip to content

Commit a732a2d

Browse files
committed
Convert vec::windowed to an external iterator, and add an n-at-a-time chunk iterator.
1 parent 944d904 commit a732a2d

File tree

1 file changed

+132
-45
lines changed

1 file changed

+132
-45
lines changed

src/libstd/vec.rs

Lines changed: 132 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -452,27 +452,46 @@ pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) ->
452452
}
453453
}
454454

455-
/**
456-
* Iterate over all contiguous windows of length `n` of the vector `v`.
457-
*
458-
* # Example
459-
*
460-
* Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, `[3,4]`)
461-
*
462-
* ~~~ {.rust}
463-
* for windowed(2, &[1,2,3,4]) |v| {
464-
* io::println(fmt!("%?", v));
465-
* }
466-
* ~~~
467-
*
468-
*/
469-
pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) -> bool {
470-
assert!(1u <= n);
471-
if n > v.len() { return true; }
472-
for uint::range(0, v.len() - n + 1) |i| {
473-
if !it(v.slice(i, i + n)) { return false; }
455+
/// An iterator over the (overlapping) slices of length `size` within
456+
/// a vector.
457+
pub struct VecWindowIter<'self, T> {
458+
priv v: &'self [T],
459+
priv size: uint
460+
}
461+
462+
impl<'self, T> Iterator<&'self [T]> for VecWindowIter<'self, T> {
463+
fn next(&mut self) -> Option<&'self [T]> {
464+
if self.size > self.v.len() {
465+
None
466+
} else {
467+
let ret = Some(self.v.slice(0, self.size));
468+
self.v = self.v.slice(1, self.v.len());
469+
ret
470+
}
471+
}
472+
}
473+
474+
/// An iterator over a vector in (non-overlapping) chunks (`size`
475+
/// elements at a time).
476+
pub struct VecChunkIter<'self, T> {
477+
priv v: &'self [T],
478+
priv size: uint
479+
}
480+
481+
impl<'self, T> Iterator<&'self [T]> for VecChunkIter<'self, T> {
482+
fn next(&mut self) -> Option<&'self [T]> {
483+
if self.size == 0 {
484+
None
485+
} else if self.size >= self.v.len() {
486+
// finished
487+
self.size = 0;
488+
Some(self.v)
489+
} else {
490+
let ret = Some(self.v.slice(0, self.size));
491+
self.v = self.v.slice(self.size, self.v.len());
492+
ret
493+
}
474494
}
475-
return true;
476495
}
477496

478497
/**
@@ -728,6 +747,9 @@ pub trait ImmutableVector<'self, T> {
728747
fn rsplit_iter(self, pred: &'self fn(&T) -> bool) -> VecRSplitIterator<'self, T>;
729748
fn rsplitn_iter(self, n: uint, pred: &'self fn(&T) -> bool) -> VecRSplitIterator<'self, T>;
730749

750+
fn window_iter(self, size: uint) -> VecWindowIter<'self, T>;
751+
fn chunk_iter(self, size: uint) -> VecChunkIter<'self, T>;
752+
731753
fn head(&self) -> &'self T;
732754
fn head_opt(&self) -> Option<&'self T>;
733755
fn tail(&self) -> &'self [T];
@@ -817,6 +839,62 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
817839
}
818840
}
819841

842+
/**
843+
* Returns an iterator over all contiguous windows of length
844+
* `size`. The windows overlap. If the vector is shorter than
845+
* `size`, the iterator returns no values.
846+
*
847+
* # Failure
848+
*
849+
* Fails if `size` is 0.
850+
*
851+
* # Example
852+
*
853+
* Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`,
854+
* `[3,4]`):
855+
*
856+
* ~~~ {.rust}
857+
* let v = &[1,2,3,4];
858+
* for v.window_iter().advance |win| {
859+
* io::println(fmt!("%?", win));
860+
* }
861+
* ~~~
862+
*
863+
*/
864+
fn window_iter(self, size: uint) -> VecWindowIter<'self, T> {
865+
assert!(size != 0);
866+
VecWindowIter { v: self, size: size }
867+
}
868+
869+
/**
870+
*
871+
* Returns an iterator over `size` elements of the vector at a
872+
* time. The chunks do not overlap. If `size` does not divide the
873+
* length of the vector, then the last chunk will not have length
874+
* `size`.
875+
*
876+
* # Failure
877+
*
878+
* Fails if `size` is 0.
879+
*
880+
* # Example
881+
*
882+
* Print the vector two elements at a time (i.e. `[1,2]`,
883+
* `[3,4]`, `[5]`):
884+
*
885+
* ~~~ {.rust}
886+
* let v = &[1,2,3,4,5];
887+
* for v.chunk_iter().advance |win| {
888+
* io::println(fmt!("%?", win));
889+
* }
890+
* ~~~
891+
*
892+
*/
893+
fn chunk_iter(self, size: uint) -> VecChunkIter<'self, T> {
894+
assert!(size != 0);
895+
VecChunkIter { v: self, size: size }
896+
}
897+
820898
/// Returns the first element of a vector, failing if the vector is empty.
821899
#[inline]
822900
fn head(&self) -> &'self T {
@@ -2663,31 +2741,6 @@ mod tests {
26632741
assert_eq!([&[1], &[2], &[3]].connect_vec(&0), ~[1, 0, 2, 0, 3]);
26642742
}
26652743

2666-
#[test]
2667-
fn test_windowed () {
2668-
fn t(n: uint, expected: &[&[int]]) {
2669-
let mut i = 0;
2670-
for windowed(n, [1,2,3,4,5,6]) |v| {
2671-
assert_eq!(v, expected[i]);
2672-
i += 1;
2673-
}
2674-
2675-
// check that we actually iterated the right number of times
2676-
assert_eq!(i, expected.len());
2677-
}
2678-
t(3, &[&[1,2,3],&[2,3,4],&[3,4,5],&[4,5,6]]);
2679-
t(4, &[&[1,2,3,4],&[2,3,4,5],&[3,4,5,6]]);
2680-
t(7, &[]);
2681-
t(8, &[]);
2682-
}
2683-
2684-
#[test]
2685-
#[should_fail]
2686-
#[ignore(cfg(windows))]
2687-
fn test_windowed_() {
2688-
for windowed (0u, [1u,2u,3u,4u,5u,6u]) |_v| {}
2689-
}
2690-
26912744
#[test]
26922745
fn test_unshift() {
26932746
let mut x = ~[1, 2, 3];
@@ -3035,6 +3088,40 @@ mod tests {
30353088
assert_eq!(xs.rsplitn_iter(1, |x| *x == 5).collect::<~[&[int]]>(), ~[&[]]);
30363089
}
30373090

3091+
#[test]
3092+
fn test_window_iterator() {
3093+
let v = &[1i,2,3,4];
3094+
3095+
assert_eq!(v.window_iter(2).collect::<~[&[int]]>(), ~[&[1,2], &[2,3], &[3,4]]);
3096+
assert_eq!(v.window_iter(3).collect::<~[&[int]]>(), ~[&[1i,2,3], &[2,3,4]]);
3097+
assert!(v.window_iter(6).next().is_none());
3098+
}
3099+
3100+
#[test]
3101+
#[should_fail]
3102+
#[ignore(cfg(windows))]
3103+
fn test_window_iterator_0() {
3104+
let v = &[1i,2,3,4];
3105+
let _it = v.window_iter(0);
3106+
}
3107+
3108+
#[test]
3109+
fn test_chunk_iterator() {
3110+
let v = &[1i,2,3,4,5];
3111+
3112+
assert_eq!(v.chunk_iter(2).collect::<~[&[int]]>(), ~[&[1i,2], &[3,4], &[5]]);
3113+
assert_eq!(v.chunk_iter(3).collect::<~[&[int]]>(), ~[&[1i,2,3], &[4,5]]);
3114+
assert_eq!(v.chunk_iter(6).collect::<~[&[int]]>(), ~[&[1i,2,3,4,5]]);
3115+
}
3116+
3117+
#[test]
3118+
#[should_fail]
3119+
#[ignore(cfg(windows))]
3120+
fn test_chunk_iterator_0() {
3121+
let v = &[1i,2,3,4];
3122+
let _it = v.chunk_iter(0);
3123+
}
3124+
30383125
#[test]
30393126
fn test_move_from() {
30403127
let mut a = [1,2,3,4,5];

0 commit comments

Comments
 (0)