处理 for 循环中的“借用的值寿命不够长”

Mir*_*asi 4 ownership rust

我正在抓取的网站要求我查询 HTML 页面的标题标签以及一些其他元素,看看我是否可以辨别文章的标题。

我创建一个HashMap<&str, u8>并立即.insert(title_tag_text, 1)查询标题元素,然后我希望将标题标签的文本类似地插入到哈希映射中,但我收到错误borrowed value does not live long enough

我不确定我是否理解,因为我认为我正确地取消引用了应该实现该特征的std::string::Stringa ?不幸的是,我怀疑我计划实现的下一个代码也有类似的问题。&strCopy

let mut title_candidates: HashMap<&str, u8> = HashMap::new();

let title_tag_text: String = Selector::parse("title")
    .ok()
    .and_then(|selector| html_document.select(&selector).next())
    .map(|elem| elem.inner_html())?;

title_candidates.insert(&*title_tag_text, 1);

Selector::parse("h1, h2, h3, .title")
    .ok()
    .as_ref()
    .map(|selector| html_document.select(selector))?
    .map(|elem| elem.inner_html()) // std::string::String
    .for_each(|title| {
        *title_candidates.entry(&*title).or_insert(0) += 1;
        // if title_tag_text.contains(&*title.as_str()) {
        //     *title_candidates.entry(&*title_tag_text) += 1;
        // }
    });

Run Code Online (Sandbox Code Playgroud)
error[E0597]: `title` does not live long enough
   --> src/main.rs:140:39
    |
125 |     let mut title_candidates: HashMap<&str, u8> = HashMap::new();
    |         -------------------- lifetime `'1` appears in the type of `title_candidates`
...
140 |             *title_candidates.entry(&*title).or_insert(0) += 1;
    |              -------------------------^^^^^-
    |              |                        |
    |              |                        borrowed value does not live long enough
    |              argument requires that `title` is borrowed for `'1`
...
144 |         });
    |         - `title` dropped here while still borrowed
Run Code Online (Sandbox Code Playgroud)

ssh*_*124 6

HashMap的钥匙是有型的&str。这意味着HashMaponly 持有对 a 的引用str,而不是其str自身。因此,为了使 中的数据HashMap有效,对 的引用str应该至少与 一样长HashMap。现在的问题是,String正在创建.map(|elem| elem.inner_html()),因此在该语句完成后它会被删除。

相反,创建一个HashMap使用拥有的 String而不是引用的。以下是一个简化示例,您可以根据自己的情况进行调整:

fn main() {
    let mut data: HashMap<String, i32> = HashMap::new();

    (0..20)
        .map(|i| (i % 10).to_string())
        .for_each(|text| {
            *data.entry(text).or_insert(0) += 1;
        });
}
Run Code Online (Sandbox Code Playgroud)

在这里,.map(|i| (i % 10).to_string())创建一个String,然后将其所有权传递给HashMapin data.entry(text),从而避免引用生命周期中的任何不匹配。

铁锈游乐场