获取迭代器的第一个元素和所有元素。在Rust中。

3

我想要做什么

我从std::str::SplitWhitespace返回了一个迭代器,我需要第一个元素和所有元素的向量。

我尝试过的方法

我尝试使用peek。然而,这似乎需要一个可变的引用(我不知道为什么),结果我遇到了借用错误。

带有编译错误的简化代码。

fn main(){
    let line = "hello, world";
    let mut tokens = line.split_whitespace().peekable();
    if let Some(first) = tokens.peek() {
        //println!("{first}"); //works
        //println!("{tokens:?}"); // works
        println!("{first}\n{tokens:?}"); //compile error
    }
}

error[E0502]: cannot borrow `tokens` as immutable because it is also borrowed as mutable
 --> src/main.rs:7:29
  |
4 |     if let Some(first) = tokens.peek() {
  |                          ------------- mutable borrow occurs here
...
7 |         println!("{first}\n{tokens:?}"); //error
  |         --------------------^^^^^^-----
  |         |                   |
  |         |                   immutable borrow occurs here
  |         mutable borrow later used here

如果我取消注释两个println并注释掉错误的那个,那么它就能工作。这让我添加了一个克隆let first = first.clone();println之前。这样修复了问题,但我想知道是否有更好的方法。

&strCopylet first = *first; 就足够了。 - Chayim Friedman
@ChayimFriedman 如果您能在回答中给一个解释的话,我会很感激,并且会点赞。我已经尝试过并且它可行。我认为我知道原因了。我假设 if let Some(&first) 也可以起作用。它确实可以,并且文本更少。 - ctrl-alt-delor
@ChayimFriedman 我还在努力理解它。我想知道为什么原始代码不起作用。我的工作假设是,如果我们后面不使用 first,那么它可以被释放:不会与其他引用同时处于活动状态。这与 https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/references-and-borrowing.htm 相矛盾。该网站指出,当其超出范围时(而不是最后一次使用后),它将被释放。然而,有一个编译不通过的代码示例是错误的。它确实可以编译。自那时以来规则是否已经放宽? - ctrl-alt-delor
1
什么是非词法生命周期? - Chayim Friedman
1个回答

5
实现这个最简单的方法就是收集向量,然后获取第一个元素:
let tokens: Vec<_> = line.split_whitespace().collect();
if let Some(first) = tokens.first() {
    println!("{first}\n{tokens:?}");
}

请注意,tokens的类型将是 Vec<&str> -- 一系列从 line 借用的字符串切片。如果您想要一个拥有所有权的字符串向量 (Vec<String>),那么需要将每个元素映射到一个拥有所有权的字符串:

let tokens: Vec<_> = line.split_whitespace().map(|s| s.to_owned()).collect();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接