I have two iterators that I want to iterate over together, but instead of advancing them both in lockstep I want to reuse the same element from one iterator when I advance the other one based on a condition. Here's some example code that hopefully makes my problem clear.
struct MyStruct {
items: Vec<Item>,
}
struct Item {
index: u32,
value: String,
}
fn main() {
let main_iter = (0..12).into_iter();
let my_struct = MyStruct {
items: vec![
Item {
index: 0,
value: "a".to_string(),
},
Item {
index: 3,
value: "b".to_string(),
},
Item {
index: 5,
value: "c".to_string(),
},
Item {
index: 8,
value: "d".to_string(),
},
],
};
let mut my_items_iter = my_struct.items.into_iter().peekable();
let new_iter = main_iter.map(move |i| {
let item = if i <= my_items_iter.peek().unwrap().index {
// Here I want to return the current value of the iterator
my_items_iter.peek().unwrap()
} else {
// Here I want to get the next value
my_items_iter.next();
my_items_iter.peek().unwrap()
};
some_function(i, &item.value)
});
// In my real code the iterator is run on another thread
let handle = std::thread::spawn(move || {
new_iter.for_each(|i| println!("{}", i));
});
handle.join().unwrap();
}
fn some_function(int: u32, string: &String) -> String {
format!("{}: {}", int, string)
}
What I'm trying to do here is align the items from both iterators based on a index value by only advancing 'my_items_iter` if the current item does not have a matching index. The desired output is
0: a
1: a
2: a
3: b
4: b
5: c
6: c
7: c
8: d
9: d
10: d
11: d
This almost works but the items from the second iterator are slightly off and I get output
0: a
1: b
2: b
3: b
4: c
5: c
6: d
7: d
8: d
and then the thread panics because my_items_iter
ran out of items.
I tried various other ways of checking the condition but I can't figure out how to solve this. I also had a look at the peekmore crate which has a PeekMoreIterator
that allows you to peak ahead more than one item but I'm not convinced I even need that here.
Any pointers in the right direction would be very welcome.