2014-11-14 35 views
0

我正在使用CSV,所以我需要修剪換行符,並在每行的逗號分隔,並篩選出有'?'在他們中。生鏽的字符串生存期和迭代器適配器(生存期編譯錯誤)

let instances: Vec<Vec<&str>> = file.lines() 
    .map(|x| x.unwrap()) 
    .filter(|x| !(x.contains("?"))) 
    .map(|x| x.as_slice().trim_chars('\n').split_str(",").collect()).collect(); 

這是編譯器錯誤消息我得到:

.../src/main.rs:13:18: 13:19 error: `x` does not live long enough 
.../src/main.rs:13   .map(|x| x.as_slice().trim_chars('\n').split_str(",").collect()).collect(); 
                  ^
.../src/main.rs:7:11: 21:2 note: reference must be valid for the block at 7:10... 
.../src/main.rs:7 fn main() { 
.../src/main.rs:8  let path = Path::new("./..."); 
.../src/main.rs:9  let mut file = BufferedReader::new(File::open(&path)); 
.../src/main.rs:10  let instances: Vec<Vec<&str>> = file.lines() 
.../src/main.rs:11   .map(|x| x.unwrap()) 
.../src/main.rs:12   .filter(|x| !(x.contains("?"))) 
              ... 
.../src/main.rs:13:18: 13:72 note: ...but borrowed value is only valid for the block at 13:17 
.../src/main.rs:13   .map(|x| x.as_slice().trim_chars('\n').split_str(",").collect()).collect(); 

我不知道如何在魯斯特的字符串類型的壽命都應該在此背景下使用。將instances更改爲Vec<Vec<String>>也不能解決問題。

什麼額外的困惑,我是在與一個String作品:

let x: Vec<&str> = some_string.as_slice().trim_chars('\n').split_str(",").collect(); 

我在做什麼不對這些值的壽命造成此編譯器錯誤?

如果迭代器適配器不是這種問題的慣用方法,請解釋爲什麼以及如何以不同的方式處理這個問題。

+2

如果你想讀取CSV數據,那麼你應該使用正確的解析器。 :) https://github.com/BurntSushi/rust-csv – BurntSushi5 2014-11-15 10:46:26

+0

@ BurntSushi5:特別是因爲分裂','沒有考慮到'''是一個壞主意...... – 2014-11-15 14:21:13

回答

2

x&str是對String的內容的引用,所述內容由lines()產生。一個&str只能生活只要String這是一個參考,並且你沒有存儲String任何地方。您需要到線或者存儲在另一個變量:

let lines = file.lines().map(|x| x.unwrap()).collect::<Vec<_>>(); 
let instances: Vec<Vec<&str>> = lines.iter() 
    .filter(|x| !(x.contains("?"))) 
    .map(|x| x.trim_chars('\n').split_str(",").collect()).collect(); 

否則你會所有&str S的轉換爲String S:

let instances: Vec<Vec<String>> = file.lines() 
    .map(|x| x.unwrap()) 
    .filter(|x| !(x.contains("?"))) 
    .map(|x| x.trim_chars('\n').split_str(",") 
     .map(|x| x.into_string()).collect()).collect(); 

作爲附帶說明,collect()電話可編寫爲collect::<Vec<_>>(),允許您從instances變量中刪除類型註釋。哪個更好?由你決定。

+0

哦,哇,我試過嵌套映射但使用「to_string」而不是「into_string」... ouch。 兩種方法之間的性能/內存使用情況有任何區別嗎?具體而言,第一個消耗整個集合兩次,因爲之前存儲解包行執行其他操作? Thanks! – abdkw 2014-11-15 00:23:04

+1

'to_string'和'into_string'都能正常工作,並且在語義上是等價的;但是,目前'to_string'效率低於'into_string',因爲它使用'std: :fmt'體系結構目前正在進行分配,而不是在可能的情況下進行精確分配,最小分配爲128個字節,而'into_string'吉普斯,並且是精確的。我希望'to_string'將在未來得到修復,但我不確定。 – 2014-11-15 04:57:13