调用IntoIter的.by_ref().take().rev()后为何vec2为空?
问题分析与解决
你的问题核心是混淆了**Take迭代器的rev()方法和先收集元素再反转序列**的行为,导致原迭代器被意外消耗,最终vec2为空。
为什么vec2为空?
当你对Take迭代器调用rev()时,并不是把take(n)取出的元素反转,而是直接改变了遍历方向:
- 原本
take(n)是从原迭代器的当前开头取n个元素; - 但
Take::rev()会让迭代器从原迭代器的末尾开始取n个元素,这个过程会通过by_ref()直接操作原迭代器的内部指针,消耗掉末尾的n个元素。
在你的代码中:
- 原迭代器是
rev()后的[[3],[2],[1],[0]](对应原vec的[[0],[1],[2],[3]]反向); - 第一次
take(2).rev().collect()并没有取开头的[3],[2],而是从原迭代器的末尾取了[0],[1],同时原迭代器的内部指针被移动,导致剩余可从末尾取的元素已经耗尽; - 第二次调用
take(2).rev().collect()时,原迭代器已经没有末尾元素可取,所以得到空Vec。
正确的实现方式
如果你想实现切片rchunks的效果(从右到左分块,每个块保持原顺序),应该先把take(n)的元素收集成Vec,再反转这个Vec,而不是直接对Take迭代器调用rev():
let mut iter = vec![vec![0], vec![1], vec![2], vec![3]] .into_iter() .rev(); // 先收集take的元素,再反转Vec let vec1: Vec<_> = iter.by_ref().take(2).collect::<Vec<_>>().into_iter().rev().collect(); println!("{:?}", vec1); // 输出 [[2], [3]] let vec2: Vec<_> = iter.by_ref().take(2).collect::<Vec<_>>().into_iter().rev().collect(); println!("{:?}", vec2); // 输出 [[0], [1]]
补充说明
by_ref()并没有阻止原迭代器被消耗,它只是让你借用迭代器而不是转移所有权。当你通过借用的迭代器操作时,所有对底层迭代器的状态变更都会反映到原迭代器上——这也是你的代码中rev()影响原迭代器的原因:Take::rev()的遍历过程直接修改了原迭代器的内部指针位置。
内容的提问来源于stack exchange,提问作者Son Kaos999
相关产品推荐
相关产品推荐

