使用带有矢量的地图

use*_*018 43 rust

虽然向量最适合程序编程,但我想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]);
}
Run Code Online (Sandbox Code Playgroud)

为什么标准库中没有这样的功能?(以及std::collections::LinkedList).有没有其他方法来处理它?

Chr*_*gan 66

Rust喜欢比这更通用; 映射是在迭代器上完成的,而不是仅仅依靠向量或切片.

几个演示:

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

.collect()可能是它中最神奇的部分,并允许您将迭代器的所有元素收集到各种不同类型中,如实现者FromIterator所示.例如,T可以收集s 的迭代器Vec<T>,其中chars可以被收集到a String,(K, V)成对的a HashMap<K, V>等等.

这种使用迭代器的方式也意味着你甚至不需要创建其他语言或其他技术的中间向量; 这样更有效,通常也很自然.


She*_*ter 14

正如bluss所指出,你也可以使用mutable迭代器来改变值,而不改变类型:

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

该函数Vec::map_in_place在Rust 1.3中已弃用,并且在Rust 1.4中不再存在.

克里斯摩根的回答是99%的最佳解决方案.但是,有一个专门的函数叫做Vec::map_in_place.这样做的好处是不需要任何额外的内存分配,但它要求输入和输出类型大小相同(感谢Levans)并且当前不稳定:

fn map_in_place<U, F>(self, f: F) -> Vec<U> 
    where F: FnMut(T) -> U
Run Code Online (Sandbox Code Playgroud)

一个例子:

#![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);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您不需要map_in_place的神奇类型更改,则可以使用可变迭代器.`for elt in&mut v {*elt =*elt + 1; }` (3认同)
  • 有人知道为什么“Vec::map_in_place”被弃用吗?文档说“不清楚 API 是否足够强大并且没有证明自己”,但我真的不知道这是什么意思...... (3认同)
  • 通过 https://github.com/rust-lang/rust/issues/75087 发现,https://github.com/rust-lang/rust/pull/70793 添加了对 into_iter()…collect() 链的优化;请参阅 https://github.com/rust-lang/rust/blob/master/library/alloc/benches/vec.rs 中的 bench_in_place 基准测试。 (3认同)
  • 请注意,它还要求输入和输出类型具有相同的大小,当然并非总是如此. (2认同)
  • 请注意,自1.3版本起,不推荐使用map_in_place。我猜我们现在使用`.into_iter()。map(...)。collect()`吗? (2认同)