2015-05-04 64 views
25

儘管矢量最適合用於程序編程,但我想對它們使用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)。是否有另一種方式來處理它?

回答

41

鐵鏽喜歡比它更普遍;映射是通過迭代器完成的,而不是單獨的向量或片。

一對夫婦示威:

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()大概是它最神奇的部分,讓你的迭代器的所有元素收集到了大量各種不同類型的,如圖所示由implementors of FromIterator。例如,T的迭代器可被收集到Vec<T>,其中char可被收集到String(K, V)對到HashMap<K, V>等等。

這種使用迭代器的方式也意味着您甚至不需要創建其他語言或其他技術的中間向量;這是更高效的,並且通常是自然的。

9

正如指出的by bluss,您還可以使用可變迭代變異到位的價值,而不改變類型:

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

功能Vec::map_in_place在拉斯特1.3過時,不再存在於Rust 1.4中。

克里斯摩根的答案是最好的解決方案99%的時間。但是,有一個稱爲Vec::map_in_place的專用功能。這具有不需要任何附加的存儲器分配的益處,但它要求的輸入和輸出類型是相同的大小(thanks 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); 
} 
+3

如果你不需要map_in_place的神奇的類型改變,你可以使用可變的迭代器。 'for elt in&mut v {* elt = * elt + 1; }' – bluss

+2

請注意,它也需要輸入和輸出類型具有相同的大小,當然並非總是如此。 – Levans

+1

注意'map_in_place'從1.3開始已被棄用。我想我們現在使用'.into_iter()。map(...).collect()'? – kennytm