Rust如何获取Vec中第二个匹配指定条件元素的索引
Rust 查找Vec中第二个true的索引的惯用实现
问题背景
给定如下布尔类型Vec定义:
let v: Vec<bool> = [false, true, false, true, false, false];
需求是获取序列中第二个值为true的元素的索引位置,以上述示例为例,目标返回值为Some(3)。
初始实现存在冗余、不符合Rust惯用风格、甚至有编译错误和逻辑隐患,初始代码如下:
fn get_second_index(v: Vec<bool>) -> Option<u32> { let mut num_matching = 0; let mut second_index = 0; for (i, b) in v.iter().enumerate() { if *b { num_matching += 1; } if num_matching == 2 { second_index = i; } } if second_index == 0 { return None; } second_index }
初始实现的主要问题:拿走Vec所有权导致外部后续无法使用该Vec、找到目标后不终止遍历做无用功、返回值类型不匹配无法编译、用索引值0作为未找到的判断条件鲁棒性差。
推荐实现方案
以下实现均符合Rust迭代器惯用写法,自动处理匹配项不足的边界场景,找到目标后立刻终止遍历无额外性能损耗,接口设计更通用。
方案1:迭代器组合写法(最简洁通用)
利用迭代器适配器筛选匹配项后直接取第2个结果,代码最短,逻辑最清晰:
fn get_second_index(v: &[bool]) -> Option<usize> { v.iter() .enumerate() .filter(|(_, &val)| val) .map(|(idx, _)| idx) .nth(1) }
- 入参使用
&[bool]切片类型,兼容Vec、数组等所有连续存储的布尔序列,且不获取所有权,不影响外部后续使用 - 返回值使用Rust集合原生索引类型
usize,无需额外类型转换 - 迭代器惰性执行,
nth(1)取到第二个匹配项后立刻停止遍历,不会遍历完整序列 - 匹配项数量不足2时自动返回
None,无需手动写边界判断
方案2:find_map自定义逻辑写法
适合匹配规则更复杂的场景,遍历过程中维护计数,找到目标立刻返回:
fn get_second_index(v: &[bool]) -> Option<usize> { let mut true_count = 0; v.iter().enumerate().find_map(|(idx, &val)| { if val { true_count += 1; (true_count == 2).then_some(idx) } else { None } }) }
性能和方案1几乎一致,逻辑更直白,可灵活扩展多条件匹配、计数规则调整等需求。
方案3:修正后的手动循环写法
如果偏好显式循环写法,可在原逻辑基础上修正问题,找到目标后立刻终止遍历,用Option存储结果避免索引值判断的逻辑隐患:
fn get_second_index(v: &[bool]) -> Option<usize> { let mut true_count = 0; let mut res = None; for (idx, &val) in v.iter().enumerate() { if val { true_count += 1; if true_count == 2 { res = Some(idx); break; } } } res }
内容的提问来源于stack exchange,提问作者mathmonkey
相关产品推荐
相关产品推荐

