如何获取由Option组成的子切片而非子切片的Option?
如何获取由Option组成的子切片而非子切片的Option?
这确实是个有意思的需求!Rust标准库的slice::get方法设计逻辑是:只有当整个输入范围完全落在切片边界内时,才返回包含子切片的Some;只要范围有任何部分越界,就直接返回None。但要实现你想要的——对范围内的每个索引单独做存在性检查,返回由Option<&T>组成的集合——我们可以自己写个简单的工具函数来搞定。
实现思路
核心逻辑很简单:遍历目标范围里的每一个索引,对每个索引调用slice.get(index)(这个方法本身就会返回对应位置元素的Option,越界则为None),最后把这些结果收集起来即可。
代码实现
我们可以写一个支持所有RangeBounds类型(比如0..2、1..=3、..4这类)的函数:
fn get_options<T>(slice: &[T], range: impl std::ops::RangeBounds<usize>) -> Vec<Option<&T>> { // 解析范围的起始索引 let start = match range.start_bound() { std::ops::Bound::Included(&s) => s, std::ops::Bound::Excluded(&s) => s + 1, std::ops::Bound::Unbounded => 0, }; // 解析范围的结束索引(转成左闭右开的形式) let end = match range.end_bound() { std::ops::Bound::Included(&e) => e + 1, std::ops::Bound::Excluded(&e) => e, std::ops::Bound::Unbounded => slice.len(), }; // 遍历每个索引,收集对应的Option (start..end).map(|i| slice.get(i)).collect() }
测试你的例子
用你给出的切片来验证:
let v = [10, 40, 30]; let result = get_options(&v, 0..4); assert_eq!(result, vec![Some(&10), Some(&40), Some(&30), None]);
进阶:返回迭代器(更高效)
如果不需要立即收集成Vec,可以直接返回迭代器,避免不必要的内存分配:
fn get_options_iter<T>(slice: &[T], range: impl std::ops::RangeBounds<usize>) -> impl Iterator<Item = Option<&T>> { let start = match range.start_bound() { std::ops::Bound::Included(&s) => s, std::ops::Bound::Excluded(&s) => s + 1, std::ops::Bound::Unbounded => 0, }; let end = match range.end_bound() { std::ops::Bound::Included(&e) => e + 1, std::ops::Bound::Excluded(&e) => e, std::ops::Bound::Unbounded => slice.len(), }; (start..end).map(move |i| slice.get(i)) }
使用的时候可以直接迭代处理,比如:
for item in get_options_iter(&v, 0..4) { println!("{:?}", item); } // 输出: // Some(10) // Some(40) // Some(30) // None
备注:内容来源于stack exchange,提问作者Sun of A beach
相关产品推荐
相关产品推荐

