遍历二维Vec<Vec<u32>>时闭包生命周期报错的解决求助
问题:遍历二维数组判断右侧是否存在更大值的闭包生命周期错误
我拥有一个Vec<Vec<u32>>类型的二维数组,想要遍历其中每个元素,判断其右侧是否存在更大的数值。以下是我的代码片段:
matrix .iter() .enumerate() .flat_map(|(y, row)| { row.iter() .enumerate() .filter(|(x, cell)| (*x..row.len()).find(|x| &matrix[y][*x] > *cell).is_none()) }) .collect::<Vec<_>>();
但这段代码返回了如下错误:
error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function --> src/main.rs:16:25 | 16 | .filter(|(x, cell)| (*x..row.len()).find(|x| &matrix[y][*x] > *cell).is_none()) | ^^^^^^^^^^^ may outlive borrowed value `y` - `y` is borrowed here | note: closure is returned here --> src/main.rs:14:13 | 14 | / row.iter() 15 | | .enumerate() 16 | | .filter(|(x, cell)| (*x..row.len()).find(|x| &matrix[y][*x] > *cell).is_none()) | |_______________________________________________________________________________________________^ help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword | 16 | .filter(move |(x, cell)| (*x..row.len()).find(|x| &matrix[y][*x] > *cell).is_none()) | ++++
当我添加move关键字后,又出现了新的错误:
error[E0507]: cannot move out of `matrix`, a captured variable in an `FnMut` closure --> src/main.rs:16:25 | 9 | let matrix = prepare_matrix(); | ------ captured outer variable ... 13 | .flat_map(|(y, row)| { | ___________________- 14 | | row.iter() 15 | | .enumerate() 16 | | .filter(move |(x, cell)| (*x..row.len()).find(|x| &matrix[y][*x] > *cell).is_none()) | | ^^^^^^^^^^^^^^^^ ------ | | | | | | | variable moved due to use in closure | | | move occurs because `matrix` has type `Vec<Vec<u32>>`, which does not implement the `Copy` trait | | move out of `matrix` occurs here 17 | | }) | |_________- captured by this `FnMut` closure
我尝试克隆matrix并基于克隆进行比较,但也无法解决问题。请问该如何修复这个错误?
解决方案
优化版代码(推荐)
直接利用当前行的切片进行判断,避免捕获整个二维数组,同时用any替代find提升效率:
matrix .iter() .enumerate() .flat_map(|(y, row)| { row.iter() .enumerate() .filter(move |(x, cell)| { // 从当前元素的下一个位置开始,检查是否存在更大的值 row[*x + 1..].iter().any(|&val| val > **cell) }) }) .collect::<Vec<_>>();
若需通过原数组索引访问的修复方案
如果场景需要通过原二维数组的索引进行操作,可以先获取数组的不可变引用,避免所有权转移问题:
let matrix_ref = &matrix; matrix .iter() .enumerate() .flat_map(|(y, row)| { row.iter() .enumerate() .filter(move |(x, cell)| { // 跳过当前元素,检查右侧所有元素 (*x + 1..row.len()).any(|x_idx| matrix_ref[y][x_idx] > **cell) }) }) .collect::<Vec<_>>();
错误原因解析
- E0373错误:
filter闭包捕获了flat_map闭包中的y,但Rust无法保证y的生命周期能覆盖filter迭代器的存活周期,因此要求用move将y的所有权转移给filter闭包。 - E0507错误:添加
move后,闭包尝试获取matrix的所有权,但flat_map的闭包是FnMut类型(会被多次调用),每次调用都会尝试移动matrix,而Vec<Vec<u32>>未实现Copytrait,无法重复转移所有权,因此报错。
内容的提问来源于stack exchange,提问作者Djent
相关产品推荐
相关产品推荐

