首页 文章

从循环内部存入借来的值到外部范围的容器?

提问于
浏览
3

我为自己设定了一项小任务,以获得一些基本的Rust知识 . 任务是:

从stdin读取一些键值对并将它们放入hashmap中 .

然而,事实证明这是一个比预期更棘手的挑战 . 主要是由于对生命的理解 . 以下代码是我目前在几次实验后得到的代码,但编译器并没有停止对我大喊大叫 .

use std::io;
use std::collections::HashMap;

fn main() {
    let mut input       = io::stdin(); 
    let mut lock        = input.lock(); 
    let mut lines_iter  = lock.lines();

    let mut map         = HashMap::new();

    for line in lines_iter {
        let text                = line.ok().unwrap();
        let kv_pair: Vec<&str>  = text.words().take(2).collect();

        map.insert(kv_pair[0], kv_pair[1]);
    }

    println!("{}", map.len());
}

编译器基本上说:

`text` does not live long enough

据我了解,这是因为'text'的生命周期仅限于循环的范围 . 因此,我在循环中提取的键值对也绑定到循环边界 . 因此,将它们插入外部 Map 将导致悬空指针,因为“文本”将在每次迭代后被销毁 . (请告诉我,如果我错了)

最大的问题是:如何解决这个问题?

我的直觉说:

制作一个关键值对的“拥有副本”,并将它的生命周期“扩展”到外部范围......但我不知道如何实现这一点 .

2 回答

  • 3

    'text'的生命周期仅限于循环的范围 . 因此,我在循环中提取的键值对也绑定到循环边界 . 因此,将它们插入外部 Map 会导致悬空指针,因为“文本”将在每次迭代后被销毁 .

    听起来对我来说 .

    制作键值对的“拥有副本” .

    拥有的 &strString

    map.insert(kv_pair[0].to_string(), kv_pair[1].to_string());
    

    Edit

    原始代码如下,但我已经更新了上面的答案,更加惯用

    map.insert(String::from_str(kv_pair[0]), String::from_str(kv_pair[1]));
    
  • 1

    Rust 1.1 中,函数 words 被标记为已弃用 . 现在你应该使用 split_whitespace .

    这是一个替代解决方案,它更具功能性和惯用性(适用于 1.3 ) .

    use std::io::{self, BufRead};
    use std::collections::HashMap;
    
    fn main() {
        let stdin = io::stdin();
    
        // iterate over all lines, "change" the lines and collect into `HashMap`
        let map: HashMap<_, _> = stdin.lock().lines().filter_map(|line_res| {
            // convert `Result` to `Option` and map the `Some`-value to a pair of
            // `String`s
            line_res.ok().map(|line| {
                let kv: Vec<_> = line.split_whitespace().take(2).collect();
                (kv[0].to_owned(), kv[1].to_owned())
            })
        }).collect();
    
        println!("{}", map.len());
    }
    

相关问题