当前位置 : 主页 > 网络安全 > 测试自动化 >

性能 – 如何根据条件重复向量中的某些元素?

来源:互联网 收集:自由互联 发布时间:2021-06-22
我在 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!
我在 kata期间遇到了这个问题.我的更具可读性的实现如下:

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,即在迭代时修改它吗?
>我想,我的解决方案效率低下:我分配了很多向量,我无法保证这将被优化.是否有更好的解决方案:可读性和分配更少?

flat_map需要迭代器,因此您可以返回值的迭代器:

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
}
网友评论