【问题标题】:Rust string lifetimes and iterator adapters (lifetime compile error)Rust 字符串生命周期和迭代器适配器(生命周期编译错误)
【发布时间】:2014-11-14 23:26:18
【问题描述】:

我正在使用 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();

我不明白在这种情况下应该如何使用 Rust 中字符串类型的生命周期。将instances 更改为Vec&lt;Vec&lt;String&gt;&gt; 也不能解决问题。

让我更加困惑的是,以下内容适用于单个字符串:

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

我在这些值的生命周期中做错了什么导致此编译器错误?

如果迭代器适配器不是解决这个问题的惯用方法,请解释我为什么以及如何以不同的方式处理这个问题。

【问题讨论】:

  • 如果你想读取 CSV 数据,那么你应该使用合适的解析器。 :) github.com/BurntSushi/rust-csv
  • @BurntSushi5:特别是因为在不考虑" 的情况下拆分, 是个坏主意...

标签: rust


【解决方案1】:

x &amp;str 是对String 内容的引用,这些内容由lines() 产生。 &amp;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();

否则您会将所有&amp;strs 转换为Strings:

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::&lt;Vec&lt;_&gt;&gt;(),允许您从instances 变量中删除类型注释。哪个更好?由您决定。

【讨论】:

  • 哦,哇,我尝试了嵌套映射方式,但使用了“to_string”而不是“into_string”......哎呀。两种方式在性能/内存使用方面有什么区别吗?具体来说,由于在执行其他操作之前存储了展开的行,第一个是否会消耗整个集合两次?谢谢!
  • to_stringinto_string 都可以正常工作并且在语义上是等效的;然而,目前,to_string 的效率低于into_string,因为它使用std::fmt 架构,该架构目前正在过度分配而不是尽可能精确,最小分配为 128 字节,而into_string 跳过了这一点并且是精确的。我希望to_string 将来会得到修复,但我不确定。
猜你喜欢
  • 2020-07-26
  • 2017-05-03
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 2013-07-03
  • 1970-01-01
  • 2017-09-28
相关资源
最近更新 更多