rust 如何在向量上使用Map?

jxct1oxe  于 2023-01-02  发布在  其他
关注(0)|答案(2)|浏览(135)

虽然向量最适合于过程编程,但我想在向量上使用map函数,下面的代码片段可以工作:

fn map<A, B>(u: &Vec<A>, f: &Fn(&A) -> B) -> Vec<B> {
    let mut res: Vec<B> = Vec::with_capacity(u.len());
    for x in u.iter() {
        res.push(f(x));
    }
    res
}

fn f(x: &i32) -> i32 {
    *x + 1
}

fn main() {
    let u = vec![1, 2, 3];
    let v = map(&u, &f);
    println!("{} {} {}", v[0], v[1], v[2]);
}

为什么在标准库中没有这样的函数(在std::collections::LinkedList中也没有)?是否有其他方法可以处理它?

f4t66c6m

f4t66c6m1#

Rust喜欢比这更笼统;Map是在迭代器上完成的,而不仅仅是在向量或切片上。
下面是几个演示:

let u = vec![1, 2, 3];
let v: Vec<_> = u.iter().map(f).collect();
let u = vec![1, 2, 3];
let v = u.iter().map(|&x| x + 1).collect::<Vec<_>>();

.collect()可能是其中最神奇的部分,它允许您将迭代器的所有元素收集到各种不同的类型中,如FromIterator的实现者所示,例如,T的迭代器可以收集到Vec<T>char的迭代器可以收集到String(K, V)对可以收集到HashMap<K, V>,等等。
这种使用迭代器的方式还意味着,您通常甚至不需要创建中间向量,而在其他语言或使用其他技术时,您需要创建中间向量;这是更有效的并且通常是自然的。

l5tcr1uw

l5tcr1uw2#

正如Bluss所指出的,您还可以使用可变迭代器在适当的位置对值进行变异,而不改变类型:

let mut nums = nums;
for num in &mut nums { *num += 1 }
println!("{:p} - {:?}", &nums, nums);

函数Vec::map_in_place在Rust 1.3中被弃用,并且在Rust 1.4中不再存在。
Chris Morgan的答案在99%的情况下都是最好的解决方案,但是有一个专门的函数Vec::map_in_place,它的好处是不需要额外的内存分配,但是它要求输入和输出类型大小相同(感谢Levans),而且目前还不稳定:

fn map_in_place<U, F>(self, f: F) -> Vec<U> 
    where F: FnMut(T) -> U

举个例子:

#![feature(collections)]

fn main() {
    let nums = vec![1,2,3];
    println!("{:p} - {:?}", &nums, nums);

    let nums = nums.map_in_place(|v| v + 1);
    println!("{:p} - {:?}", &nums, nums);
}

相关问题