首页 > 解决方案 > 在 for 循环中处理“借来的值不够长”

问题描述

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

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

我不确定我是否理解,因为我认为我正确地取消了对应该实现特征的std::string::Stringinto a 的引用?不幸的是,我怀疑我计划实现的下一个代码有类似的问题。&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;
        // }
    });

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

标签: rustownership

解决方案


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

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

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;
        });
}

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

锈游乐场


推荐阅读