我在 kata期间遇到了这个问题.我的更具可读性的实现如下: use std::vec::Vec;fn repeat_even(v: Veci32) - Veci32 { v.into_iter().flat_map(|x| match x % 2 { 0 = vec![x, x], _ = vec![x] }).collect()}fn main() { let v = vec!
use std::vec::Vec; fn repeat_even(v: Vec<i32>) -> Vec<i32> { v.into_iter().flat_map(|x| match x % 2 { 0 => vec![x, x], _ => vec![x] }).collect() } fn main() { let v = vec![1, 2, 3, 4, 6]; assert_eq!(repeat_even(v), vec![1, 2, 2, 3, 4, 4, 6, 6]); }
我有两个问题:
>是否有必要创建另一个Vec?可以使用相同的Vec,即在迭代时修改它吗?
>我想,我的解决方案效率低下:我分配了很多向量,我无法保证这将被优化.是否有更好的解决方案:可读性和分配更少?
use std::iter; fn double_even(v: &[i32]) -> Vec<i32> { v.iter().flat_map(|&x| { let count = if x % 2 == 0 { 2 } else { 1 }; iter::repeat(x).take(count) }).collect() } fn main() { let v = vec![1, 2, 3, 4, 6]; assert_eq!(double_even(&v), vec![1, 2, 2, 3, 4, 4, 6, 6]); }
注意事项:
>没有理由使用std :: vec :: Vec.它已经通过prelude进口了.
>您没有使用传入向量的内存分配,因此没有理由接受它.另见Why is it discouraged to accept a reference to a String (&String) or Vec (&Vec) as a function argument?
>不要使用vec!();使用vec![]代替.它与编译器无关,但对人类很重要.
如果你真的试图重用内存,我会沿着迭代器向后走,以帮助避免索引失效:
fn double_even(mut v: Vec<i32>) -> Vec<i32> { for i in (0..v.len()).rev() { let val = v[i]; if val % 2 == 0 { v.insert(i, val); } } v }
这可能在算法上更糟;每个插入后移动所有数据.我相信当每个元素都是偶数时,最坏的情况是O(n ^ 2).
我通常也不会在这里取价值.我会采取一个可变的参考.如果你确实需要它,你总是可以将它包回一个值:
fn double_even_ref(v: &mut Vec<i32>) { for i in (0..v.len()).rev() { let val = v[i]; if val % 2 == 0 { v.insert(i, val); } } } fn double_even(mut v: Vec<i32>) -> Vec<i32> { double_even_ref(&mut v); v }