如何在Rust中过滤索引上的向量

ejk8hzay  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(174)

我有一个Vec<f64>,我试图得到说,每第7个元素的向量,直到我运行的界限,到另一个Vec<f64>。我想也许我可以创建一个索引的元素,我想要的,然后过滤器的基础上。但我似乎不能直接或间接地做到这一点。我试图

let x: Vec<f64> = (1..200)
.map(|x| (x as f64)/(200 as f64))
.collect();

let y: Vec<f64> = x
.enumerate()
.filter(|&(i, _)| i % 7 == 0 )
.map(|(_, e)| e)
.collect();

字符串
但这并不适用于编译错误enumerate method cannot be called on Vec<f64> due to unsatisfied trait bounds。我也发现了一个保留方法,但没有看到一种方法将其应用于索引而不是元素。令人惊讶的是,SO的健壮搜索没有产生任何结果。

aelbi1ox

aelbi1ox1#

感谢您的评论,将所有内容拼凑在一起,为社区提供一个更完整的答案。
为了根据索引过滤向量,首先我们使用into_iter创建一个迭代器,然后枚举它以获得索引,然后应用过滤器,然后使用map删除索引,最后将其收集到f64 vector。

let y: Vec<f64> = x
.into_iter()
.enumerate()
.filter(|&(i, _)| i % 2 == 0 )
.map(|(_, e)| e)
.collect();

字符串
如果y的作用域比x的作用域短,并且y中有很大的值(比如字符串),那么最好将y作为引用的向量,而不是值。

let y: Vec<&f64> = x
.iter()
.enumerate()
.filter(|&(i, _)| i % 2 == 0 )
.map(|(_, e)| e)
.collect();


这里的关键区别是使用iter()而不是into_iter()。rust book中的This page解释了这一点:
iter方法在不可变的引用上产生一个迭代器。如果我们想创建一个迭代器,它获取v1的所有权并返回所拥有的值,我们可以调用into_iter而不是iter。类似地,如果我们想在可变的引用上进行迭代,我们可以调用iter_mut而不是iter
现在,对于这个特定的问题,可能不需要对索引应用过滤器。

let y: Vec<_> = x.into_iter().step_by(2).collect();

6psbrbz9

6psbrbz92#

请注意,有一个专门的迭代器适配器step_by()

let y: Vec<_> = x.into_iter().step_by(7).collect();

字符串

lnvxswe2

lnvxswe23#

我还发现了一个保留方法,但没有看到一种方法将其应用于索引而不是元素。
虽然Vec::retain没有给予任何类型的索引,但它需要一个FnMut,并被记录为按顺序操作:
此方法在适当的位置运行,按原始顺序访问每个元素一次,并保留保留元素的顺序。
所以你可以自己跟踪索引:

let mut idx = 0;
x.retain(|_| {
    let v = idx;
    idx += 1;
    v % 2 == 0
});

字符串
或者在这里,您可以通过简单的切换进行专业化:

let mut keep = false;
x.retain(|_| {
    keep = !keep;
    keep
});

相关问题