簡體   English   中英

遍歷文件中的行並從 vec 中查找 substring! 在 rust

[英]Iterating over lines in a file and looking for substring from a vec! in rust

我正在編寫一個項目,其中可以從數據文件構建結構System 在數據文件中,一些行包含關鍵字,這些關鍵字指示要在行內或后續 N 行中讀取的值(與行之間用空行分隔)。

我想要一個vec! 包含關鍵字(在編譯時靜態已知),檢查迭代器返回的行是否包含關鍵字並執行適當的操作。

現在我的代碼看起來像這樣:

impl System {
    fn read_data<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>> where P: AsRef<Path> {
        let file = File::open(filename)?;
        let f = BufReader::new(file);
        Ok(f.lines())
    }
    ...
    pub fn new_from_data<P>(dataname: P) -> System where P: AsRef<Path> {
        let keywd = vec!["atoms", "atom types".into(),
                         "Atoms".into()];
        let mut sys = System::new();
        if let Ok(mut lines) = System::read_data(dataname) {
            while let Some(line) = lines.next() {
                for k in keywd {
                    let split: Vec<&str> = line.unwrap().split(" ").collect();
                    if split.contains(k) {
                        match k {
                        "atoms" => sys.natoms = split[0].parse().unwrap(),
                        "atom types" => sys.ntypes = split[0].parse().unwrap(),
                        "Atoms" => {
                            lines.next();
                            // assumes fields are: atom-ID molecule-ID atom-type q x y z
                            for _ in 1..=sys.natoms {
                                let atline = lines.next().unwrap().unwrap();
                                let data: Vec<&str> = atline.split(" ").collect();
                                let atid: i32 = data[0].parse().unwrap();
                                let molid: i32 = data[1].parse().unwrap();
                                let atype: i32 = data[2].parse().unwrap();
                                let charge: f32 = data[3].parse().unwrap();
                                let x: f32 = data[4].parse().unwrap();
                                let y: f32 = data[5].parse().unwrap();
                                let z: f32 = data[6].parse().unwrap();
                                let at = Atom::new(atid, molid, atype, charge, x, y, z);
                                sys.atoms.push(at);
                            };
                        },
                        _ => (),
                        }
                    }
                }
            }
        }
        sys
    }
}

我對兩點非常不確定:

  1. 我不知道我是否以慣用的方式逐行讀取文件,因為我修改了書中的一些示例,並舉例說明了 Rust。 但是返回一個迭代器讓我想知道何時以及如何解包結果。 例如,當在 while 循環中調用迭代器時,我是否必須像let atline = lines.next().unwrap().unwrap();那樣解包兩次? 我認為編譯器還沒有抱怨,因為它遇到的第一個錯誤是
  2. 當我得到一個典型值時,我無法圍繞賦予值 k 的類型進行思考:
error[E0308]: mismatched types
 --> src/system/system.rs:65:39
  |
65 |                     if split.contains(k) {
  |                                       ^ expected `&str`, found `str`
  |
  = note: expected reference `&&str`
             found reference `&str`

error: aborting due to previous error

我們應該如何聲明 substring 並將其與我放入keywd的字符串進行比較? 我試圖在 contains 中引用 k,告訴它查看 &keywd 等,但我只是覺得我在浪費時間,因為我沒有正確解決問題。 提前致謝,非常感謝您的幫助。

讓我們 go 一一道來。 我將 go 通過它們出現在代碼中。

首先需要在for循環中借用keywd ,即&keywd 因為否則keywdwhile循環的第一次迭代之后被移動,因此編譯器為什么會抱怨這個。

for k in &keywd {
    let split: Vec<&str> = line.unwrap().split(" ").collect();

接下來,當您line調用.unwrap()時,這是同樣的問題。 這導致內部Ok值從Result中移出。 相反,您可以執行line.as_ref().unwrap() ,因為這樣您就可以獲得對內部Ok值的引用,並且不會使用結果line

或者,您可以.filter_map(Result::ok)在您的lines上,以避免( .as_ref().unwrap()完全。

您可以將其直接添加到read_data中,甚至可以使用impl...將其簡單地添加到返回類型中。

fn read_data<P>(filename: P) -> io::Result<impl Iterator<Item = String>>
where
    P: AsRef<Path>,
{
    let file = File::open(filename)?;
    let f = BufReader::new(file);
    Ok(f.lines().filter_map(Result::ok))
}

請注意,您正在為每個keywd拆分line ,這是不必要的。 所以你也可以把它移到你的for循環之外。

總而言之,它最終看起來像這樣:

if let Ok(mut lines) = read_data("test.txt") {
    while let Some(line) = lines.next() {
        let split: Vec<&str> = line.split(" ").collect();
        for k in &keywd {
            if split.contains(k) {
                ...

鑒於我們借用了&keywd ,那么我們不需要將k更改為&k ,因為現在k已經是&&str

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM