Open
Description
I'm not really sure of the right words to describe what I'm looking for, so possibly this already exists.
I'd like something that is like zipping an iterator with one or more staggered copies of itself. For example, for a window size of 3, on an iterator over [1, 2, 3, 4, 5]
, this would yield:
(None, 1)
(Some((None , 1 )), 2)
(Some((Some(1), 2 )), 3)
(Some((Some(2), 3 )), 4)
(Some((Some(3), 4 )), 5)
I wanted this for a machine learning application where I'm trying to predict the next element of a sequence given the previous N
elements. Perhaps this is also useful for other purposes, but I'm not sure that it is.
I have implemented a proof-of-concept. Although the code could be improved in many ways, I think it's correct. If this would be an interesting addition to itertools
, I'd be happy to refine these implementations to fix some of the issues.
/// Given an iterator [1, 2, 3, 4], this will yield:
/// (None, 1)
/// (Some(1), 2)
/// (Some(2), 3)
/// (Some(3), 4)
pub fn tuple2_windows_prefix<T: Clone, I: Iterator<Item = T>>(
iterator: I,
) -> impl Iterator<Item = (Option<T>, T)> {
iterator.scan(None, |previous_item, this_item| {
let to_return = (previous_item.clone(), this_item.clone());
*previous_item = Some(this_item.clone());
Some(to_return)
})
}
#[test]
fn test_tuple2_windows_prefix() {
assert_eq!(
vec![(None, 1), (Some(1), 2), (Some(2), 3)],
tuple2_windows_prefix(vec![1, 2, 3].into_iter()).collect_vec()
)
}
/// Given an iterator [1, 2, 3, 4, 5], this will yield:
/// (None, 1)
/// (Some((None , 1 )), 2)
/// (Some((Some(1), 2 )), 3)
/// (Some((Some(2), 3 )), 4)
/// (Some((Some(3), 4 )), 5)
pub fn tuple3_windows_prefix<T: Clone, I: Iterator<Item = T>>(
iterator: I,
) -> impl Iterator<Item = (Option<(Option<T>, T)>, T)> {
iterator.scan(None, |previous_items, this_item| {
let previous_items: &mut Option<(Option<T>, T)> = previous_items;
let (previous_items_new, to_return) = match previous_items {
None => (Some((None, this_item.clone())), (None, this_item)),
Some((None, previous_item)) => (
Some((Some(previous_item.clone()), this_item.clone())),
(Some((None, previous_item.clone())), this_item),
),
Some((Some(previous2_item), previous_item)) => (
Some((Some(previous_item.clone()), this_item.clone())),
(
Some((Some(previous2_item.clone()), previous_item.clone())),
this_item,
),
),
};
*previous_items = previous_items_new;
Some(to_return)
})
}
#[test]
fn test_tuple3_windows_prefix() {
assert_eq!(
vec![
(None, 1),
(Some((None, 1)), 2),
(Some((Some(1), 2)), 3),
(Some((Some(2), 3)), 4)
],
tuple3_windows_prefix(vec![1, 2, 3, 4].into_iter()).collect_vec()
)
}
Metadata
Metadata
Assignees
Labels
No labels