1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
//! # VecAltern
//!
//! The `vec_altern` module provides an iterator, `VecAltern`, for alternately traversing multiple iterators.
//!
//! ## Usage
//!
//! To use `VecAltern`, create a new instance with `VecAltern::new()` and add iterators using the `add` method (or `add_and` for a build pattern).
//! You can also use the macro `altern` for more concise syntax and little performance optimization.
//! The `next` method will then yield elements from the added iterators in a round-robin fashion until all iterators are exhausted.
//!
//! ## Examples
//!
//! ```rust
//! use combin_iterator::altern::VecAltern;
//! let vec1 = vec![1, 4, 7, 9];
//! let vec2 = vec![2, 5];
//! let vec3 = vec![3, 6, 8];
//!
//! // // Create a VecAltern iterator and add individual iterators, with a build pattern.
//! let mut iter = VecAltern::new();
//! iter.add(vec1.iter());
//! iter.add(vec2.iter());
//! iter.add(vec3.iter());
//!
//! assert_eq!(iter.collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6, &7, &8, &9]);
//!
//! // You can also use a build pattern:
//! let iter = VecAltern::new().add_and(vec1.iter()).add_and(vec2.iter()).add_and(vec3.iter());
//! assert_eq!(iter.collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6, &7, &8, &9]);
//!
//! // Alternatively, use the `altern!` macro for a more concise syntax, and some perfomance optimization
//! use combin_iterator::altern;
//! let iter_macro = altern!(vec1.iter(), vec2.iter(), vec3.iter());
//!
//! // Both iterators should yield the same results
//! assert_eq!(iter_macro.collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6, &7, &8, &9]);
//! ```
//!
//! ## Notes
//!
//! - The `altern!` macro provides a convenient way to create an `Altern` iterator with a cleaner syntax, and
//! a little performance optimization (with the function: `with_capacity`, like in `Vec`). If you know at
//! compile time how many iter you will altern between, then use the `altern!` macro.
/// Struct to altern between several iterator
pub struct VecAltern<'a, A> {
iters: Vec<Box<dyn Iterator<Item = A> + 'a>>,
current: usize,
}
impl<'a, A> VecAltern<'a, A> {
/// Creates a new instance of an `Altern` iterator.
pub fn new() -> Self {
Self {
iters: vec![],
current: 0,
}
}
/// Prepare the capacity, like `vec::with_capacity` does.
pub fn with_capacity(capacity : usize) -> Self {
Self {
iters: Vec::with_capacity(capacity),
current: 0
}
}
/// Adds an iterator to the `Altern` instance.
///
/// # Arguments
///
/// * `iterator` - An iterator of references to elements of type `A`.
///
/// # Returns
///
/// The updated `Altern` instance with the added iterator, to use like a builder.
pub fn add_and(mut self, iterator: impl Iterator<Item = A> + 'a) -> Self {
self.iters.push(Box::new(iterator));
self
}
/// Adds an iterator to the `Altern` instance.
///
/// # Arguments
///
/// * `iterator` - An iterator of references to elements of type `A`.
///
/// # Returns
pub fn add(&mut self, iterator: impl Iterator<Item = A> + 'a){
self.iters.push(Box::new(iterator));
}
}
impl<'a, A> Iterator for VecAltern<'a, A>
{
type Item = A;
/// Returns the next element in the iteration sequence.
///
/// The `next` method alternates between the added iterators in a round-robin fashion.
fn next(&mut self) -> Option<A> {
loop {
if self.iters.is_empty() {
return None;
} else {
let next;
match self.iters.get_mut(self.current) {
Some(iter) => {
next = (*iter).next()
},
None => {
panic!("altern.current out of bound for altern.iters ")
},
}
match next {
Some(value) => {
self.current = (self.current + 1) % self.iters.len();
return Some(value)
},
None => {
let _ = self.iters.remove(self.current);
let n = self.iters.len().max(1);
self.current = self.current % n;
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::VecAltern;
#[test]
fn vec_altern() {
let vec1 = vec![1, 4, 7, 9];
let vec2 = vec![2, 5];
let vec3 = vec![3, 6, 8];
let iter = VecAltern::new().add_and(vec1.iter()).add_and(vec2.iter()).add_and(vec3.iter());
assert_eq!(iter.collect::<Vec<_>>(), vec![&1,&2,&3,&4,&5,&6,&7,&8, &9]);
}
#[test]
fn empty_vec_altern() {
let vec1 : Vec<u8> = vec![];
let vec2: Vec<u8> = vec![];
let vec3: Vec<u8> = vec![];
let mut iter = VecAltern::new().add_and(vec1.iter()).add_and(vec2.iter()).add_and(vec3.iter());
assert_eq!(iter.next(), None);
}
use crate::altern;
#[test]
fn macro_altern() {
let vec1 = vec![1, 4, 7, 9];
let vec2 = vec![2, 5];
let vec3 = vec![3, 6, 8];
let iter = altern!(vec1.iter(), vec2.iter(), vec3.iter());
assert_eq!(iter.collect::<Vec<_>>(), vec![&1,&2,&3,&4,&5,&6,&7,&8, &9]);
}
}