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

时间:2014-12-14 20:15:57

标签: rust

我为自己设定了一项任务,以获得一些基本的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

据我了解,这是因为&#39; text&#39;仅限于循环的范围。 因此,我在循环中提取的键值对也绑定到循环边界。因此,将它们插入到外部地图会导致悬空指针,因为文本&#39;每次迭代后都会被销毁。 (请告诉我,如果我错了)

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

我的直觉说:

制作一份&#34;拥有的副本&#34;键值对和&#34;扩展&#34;它的生命周期到外部范围......但我不知道如何实现这一目标。

2 个答案:

答案 0 :(得分:3)

  

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

听起来对我不错。

  

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

拥有的&strString

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

修改

原始代码如下,但我已将上面的答案更新为更惯用的

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

答案 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());
}