gpt4 book ai didi

string - 遍历文件中的行并从 vec 中查找子字符串!使用rust

转载 作者:行者123 更新时间:2023-12-03 11:44:15 25 4
gpt4 key购买 nike

我正在编写一个项目,其中结构 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
}
}
我非常不确定两点:
  • 我不知道我是否以惯用的方式逐行读取文件,因为我修补了书中的一些示例和 Rust 示例。但是返回一个迭代器让我想知道何时以及如何解开结果。例如,当在 while 循环中调用迭代器时,我必须像 let atline = lines.next().unwrap().unwrap(); 中那样解包两次吗? ?我认为编译器还没有提示,因为它遇到的第一个错误是
  • 当我得到一个典型的值时,我无法理解赋予值 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
    我们应该如何声明子字符串并将其与我放入 keywd 的字符串进行比较?我试图在包含中尊重 k,告诉它查看 &keywd 等,但我只是觉得我在浪费时间没有正确解决问题。在此先感谢,确实感谢任何帮助。

    最佳答案

    让我们一一解决问题。我将通过它们出现在代码中的内容。
    首先你需要借keywdfor循环,即 &keywd .因为否则keywdwhile 的第一次迭代后移动循环,以及为什么编译器会提示这一点。

    for k in &keywd {
    let split: Vec<&str> = line.unwrap().split(" ").collect();
    接下来,当您调用 .unwrap()line ,同样的问题。这导致内部 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))
    }
    请注意,您正在拆分 line对于每个 keywd ,这是不必要的。所以你可以把它移到你的 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 .

    关于string - 遍历文件中的行并从 vec 中查找子字符串!使用rust ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65170502/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com