I have a Vec<f64>
and I am trying to get say every 7th element of the vector till I run out of bounds, into another Vec<f64>
. I thought maybe I could create an index of the elements I want and then filter based on that. But I can't seem to be able to do this directly or indirectly. What I tried
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();
But this did not work with compile error enumerate method cannot be called on Vec<f64> due to unsatisfied trait bounds
. I also found a retain method but don't see a way to apply it on the index rather than the element. A robust search of SO surprisingly did not yield anything.
Thanks for the comments, patching everything together into a more complete answer for the community. Let's say this is the Vec: let x: Vec<f64> = (1..10).map(|x| (x as f64)/(10 as f64)).collect();
To filter the vector based on index, first we create an iterator with into_iter, then enumerate it to get index, then apply the filter, and then a map to remove the index, finally collecting it to f64 vector.
let y: Vec<f64> = x
.into_iter()
.enumerate()
.filter(|&(i, _)| i % 2 == 0 )
.map(|(_, e)| e)
.collect();
If the scope of y
is shorter than that of x
, and if you had large values in y
(say string), it might be preferable to make y
a vector of references rather than values.
let y: Vec<&f64> = x
.iter()
.enumerate()
.filter(|&(i, _)| i % 2 == 0 )
.map(|(_, e)| e)
.collect();
The key difference here is using iter()
instead of iter_into()
. This page in rust book explains it:
The iter method produces an iterator over immutable references. If we want to create an iterator that takes ownership of v1 and returns owned values, we can call
into_iter
instead ofiter
. Similarly, if we want to iterate over mutable references, we can calliter_mut
instead ofiter
.
Now, for this specific question, applying a filter to the index is probably not needed. A simpler way, as noted by Chayim below is
let y: Vec<_> = x.into_iter().step_by(2).collect();
I also found a retain method but don't see a way to apply it on the index rather than the element.
While Vec::retain
does not give you any sort of index, it takes an FnMut
and is documented to operate in-order:
This method operates in place, visiting each element exactly once in the original order , and preserves the order of the retained elements.
So you can just keep track of the index yourself:
let mut idx = 0;
x.retain(|_| {
let v = idx;
idx += 1;
v % 2 == 0
});
Or here you can specialise with a simple toggle:
let mut keep = false;
x.retain(|_| {
keep = !keep;
keep
});
请注意,有一个专门的迭代器适配器step_by()
:
let y: Vec<_> = x.into_iter().step_by(7).collect();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.