Rust双端迭代器增强库double-ended-peekable的使用,支持双向peek操作的迭代器扩展功能
Rust双端迭代器增强库double-ended-peekable的使用,支持双向peek操作的迭代器扩展功能
double-ended-peekable是一个Rust库,它为双端迭代器(实现了DoubleEndedIterator
trait的类型)提供了双向peek功能。
安装
在项目目录中运行以下Cargo命令:
cargo add double-ended-peekable
或者在Cargo.toml中添加:
double-ended-peekable = "0.1.0"
使用示例
以下是一个使用double-ended-peekable的完整示例:
use double_ended_peekable::DoubleEndedPeekableExt;
fn main() {
// 创建一个可迭代的集合
let nums = vec![1, 2, 3, 4, 5];
// 转换为双端peekable迭代器
let mut iter = nums.into_iter().double_ended_peekable();
// 从前面peek
println!("Peek from front: {:?}", iter.peek()); // Some(&1)
// 从后面peek
println!("Peek from back: {:?}", iter.peek_back()); // Some(&5)
// 遍历并打印所有元素
while let Some(num) = iter.next() {
println!("Next: {}", num);
// 在遍历过程中可以随时查看下一个或前一个元素
println!("Next peek: {:?}", iter.peek());
println!("Previous peek: {:?}", iter.peek_back());
}
}
功能特点
- 支持从迭代器前端和后端peek元素
- 不会消耗迭代器中的元素
- 与标准库中的
Peekable
迭代器类似,但增加了反向peek功能
适用场景
- 需要同时查看迭代器前后元素的算法
- 解析器或词法分析器实现
- 需要双向查看数据的处理流程
完整示例演示
下面是一个更完整的示例,展示了如何在实际场景中使用double-ended-peekable库:
use double_ended_peekable::DoubleEndedPeekableExt;
fn main() {
// 创建一个字符串切片集合
let words = vec!["Rust", "is", "awesome", "and", "fast"];
// 创建双端peekable迭代器
let mut word_iter = words.into_iter().double_ended_peekable();
// 检查前后元素
println!("First word: {:?}", word_iter.peek()); // Some("Rust")
println!("Last word: {:?}", word_iter.peek_back()); // Some("fast")
// 处理中间元素
while let Some(word) = word_iter.next() {
println!("Current word: {}", word);
// 检查是否到达中间点
if let (Some(next_word), Some(prev_word)) = (word_iter.peek(), word_iter.peek_back()) {
println!("Next word will be: {}, previous word was: {}", next_word, prev_word);
// 示例:当遇到特定词时查看前后元素
if word == "awesome" {
println!("Found 'awesome'! Before it was 'is', after it will be 'and'");
}
}
}
// 另一个示例:处理数字序列
let numbers = (1..=10).collect::<Vec<_>>();
let mut num_iter = numbers.into_iter().double_ended_peekable();
// 使用peek_back检查是否包含偶数
if let Some(last) = num_iter.peek_back() {
if last % 2 == 0 {
println!("Last number {} is even", last);
}
}
// 遍历时跳过某些元素
while let Some(n) = num_iter.next() {
if n % 3 == 0 {
println!("Skipping number divisible by 3: {}", n);
continue;
}
println!("Processing number: {}", n);
// 查看下一个元素决定是否继续
if let Some(next_n) = num_iter.peek() {
if *next_n > 7 {
println!("Next number is greater than 7, stopping early");
break;
}
}
}
}
注意事项
- 该库需要迭代器实现
DoubleEndedIterator
trait - peek操作返回的是引用,不会消耗迭代器元素
- 在迭代过程中可以随时使用peek和peek_back查看元素
- 适用于需要前瞻或后顾处理的场景
1 回复
Rust双端迭代器增强库double-ended-peekable使用指南
概述
double-ended-peekable
是一个Rust库,它为双端迭代器提供了增强的peek功能,允许你同时向前和向后查看迭代器中的元素而不会消耗它们。
功能特点
- 支持双向peek操作
- 保持原始迭代器的所有功能
- 零成本抽象(在Rust中意味着没有运行时开销)
- 与标准库的
Peekable
类似但功能更强大
安装
在Cargo.toml中添加依赖:
[dependencies]
double-ended-peekable = "0.1"
基本使用方法
创建双端peekable迭代器
use double_ended_peekable::DoubleEndedPeekableExt;
fn main() {
let vec = vec![1, 2, 3, 4, 5];
let mut iter = vec.into_iter().double_ended_peekable();
// 现在可以使用双向peek功能
}
双向peek操作
let mut iter = vec![1, 2, 3, 4, 5].into_iter().double_ended_peekable();
// 向前peek
assert_eq!(iter.peek(), Some(&1));
assert_eq!(iter.peek_next(), Some(&2));
// 向后peek
assert_eq!(iter.peek_prev(), None); // 还没有消耗任何元素
// 前进一个元素
iter.next();
// 现在可以向后peek了
assert_eq!(iter.peek_prev(), Some(&1));
assert_eq!(iter.peek(), Some(&2));
assert_eq!(iter.peek_next(), Some(&3));
完整示例
use double_ended_peekable::DoubleEndedPeekableExt;
fn process_sequence<I: DoubleEndedIterator>(iter: I) {
let mut iter = iter.double_ended_peekable();
while let Some(current) = iter.next() {
let prev = iter.peek_prev().copied();
let next = iter.peek().copied();
println!(
"Processing {}: previous was {:?}, next is {:?}",
current, prev, next
);
// 根据前后元素决定处理逻辑
match (prev, next) {
(Some(p), Some(n)) if p < current && n > current => {
println!(" -> Peak detected!");
},
(Some(p), Some(n)) if p > current && n < current => {
println!(" -> Valley detected!");
},
_ => {}
}
}
}
fn main() {
let data = vec![1, 3, 5, 4, 2, 6, 8];
process_sequence(data.into_iter());
}
高级用法
与双端迭代器结合使用
use double_ended_peekable::DoubleEndedPeekableExt;
fn main() {
let mut iter = (1..=10).double_ended_peekable();
// 从前面消耗几个元素
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
// 从后面消耗几个元素
assert_eq!(iter.next_back(), Some(10));
assert_eq!(iter.next_back(), Some(9));
// 现在peek各个方向
assert_eq!(iter.peek(), Some(&3)); // 下一个前面的元素
assert_eq!(iter.peek_next(), Some(&4)); // 下下个前面的元素
assert_eq!(iter.peek_prev(), Some(&2)); // 前一个前面的元素
assert_eq!(iter.peek_back(), Some(&8)); // 下一个后面的元素
}
实现自定义逻辑
use double_ended_peekable::DoubleEndedPeekableExt;
fn find_symmetric_pairs<I: DoubleEndedIterator<Item = i32>>(iter: I) -> Vec<(i32, i32)> {
let mut iter = iter.double_ended_peekable();
let mut result = Vec::new();
while let (Some(front), Some(back)) = (iter.peek(), iter.peek_back()) {
if front == back {
result.push((*front, *back));
iter.next();
iter.next_back();
} else if front < back {
iter.next();
} else {
iter.next_back();
}
}
result
}
fn main() {
let nums = vec![1, 2, 3, 4, 5, 4, 3, 2, 1];
let pairs = find_symmetric_pairs(nums.into_iter());
println!("Symmetric pairs: {:?}", pairs);
// 输出: Symmetric pairs: [(1, 1), (2, 2), (3, 3), (4, 4)]
}
完整示例demo
下面是一个结合了多种功能的完整示例,展示如何在实际场景中使用double-ended-peekable:
use double_ended_peekable::DoubleEndedPeekableExt;
// 处理数字序列,检测极值和趋势
fn analyze_sequence<I: DoubleEndedIterator<Item = i32>>(iter: I) {
let mut iter = iter.double_ended_peekable();
let mut count = 0;
println!("开始分析序列...");
while let Some(current) = iter.next() {
count += 1;
let prev = iter.peek_prev().copied();
let next = iter.peek().copied();
// 打印当前位置信息
println!("\n元素 #{}: {}", count, current);
println!("前驱元素: {:?}, 后继元素: {:?}", prev, next);
// 检测极值点
match (prev, next) {
(Some(p), Some(n)) if p < current && n < current => {
println!("↗↘ 检测到局部最大值: {}", current);
},
(Some(p), Some(n)) if p > current && n > current => {
println!("↘↗ 检测到局部最小值: {}", current);
},
_ => {}
}
// 检测趋势
match (prev, next) {
(Some(p), Some(n)) if p < current && current < n => {
println!("↑ 上升趋势");
},
(Some(p), Some(n)) if p > current && current > n => {
println!("↓ 下降趋势");
},
_ => {}
}
// 如果到达序列末尾
if iter.peek().is_none() {
println!("已到达序列末尾");
}
}
println!("分析完成,共处理{}个元素", count);
}
fn main() {
// 创建一个测试序列
let test_data = vec![1, 2, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2];
println!("测试序列: {:?}", test_data);
analyze_sequence(test_data.into_iter());
}
注意事项
- 该库需要迭代器实现
DoubleEndedIterator
trait peek_prev()
只有在已经消耗至少一个元素后才会返回Some- 所有peek操作都不会消耗迭代器中的元素
- 性能与标准库的
Peekable
相当
这个库特别适合需要同时查看前后元素的算法场景,如解析器、模式匹配等需要"前瞻"和"后顾"的情况。