虽然向量最适合程序编程,但我想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>
,其中char
s可以被收集到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)