4

我想使用HashSet快速字符串查找,但我似乎无法找到一种方法将字符串变量传递给contains没有编译器错误。

refs = HashSet::new();

let first_pass = link_regex.replace_all(&buffer, |caps: &Captures| {

    if caps.len() == 2 {
        refs.insert(caps.at(2).unwrap());
    }

    caps.at(1).unwrap().to_owned()
});

let out = ref_regex.replace_all(&first_pass, |caps: &Captures| {
    let capture = caps.at(1).unwrap().to_owned();

    // only remove if we've seen it before
    if refs.contains(capture) {
        return "".to_string();
    }

    capture
});

这会导致此错误:

 src/bin/remove_links.rs:30:26: 30:33 error: mismatched types [E0308]
 src/bin/remove_links.rs:30         if refs.contains(capture) {
                                                     ^~~~~~~
 src/bin/remove_links.rs:30:26: 30:33 help: run `rustc --explain E0308` to see a detailed explanation
 src/bin/remove_links.rs:30:26: 30:33 note: expected type `&_`
 src/bin/remove_links.rs:30:26: 30:33 note:    found type `std::string::String`

如果我尝试

refs.contains(&capture)

然后我得到

src/bin/remove_links.rs:30:17: 30:25 error: the trait bound `&str: std::borrow::Borrow<std::string::String>` is not satisfied [E0277]
src/bin/remove_links.rs:30         if refs.contains(&capture) {
                                           ^~~~~~~~

我很难过,我需要做某种类型转换吗?

4

1 回答 1

12

解释

首先,让我们看看refs有什么类型。此时HashSet::new(),编译器无法判断您将要放入集合中的内容类型,因此尚不清楚类型。但是编译器在这一行中计算出来:

refs.insert(caps.at(2).unwrap());

函数调用 ( caps.at(2).unwrap()) 中的表达式返回一个&str. 所以我们将&strs 放入集合中,因此refs有 type HashSet<&str>

如果您现在查看 的文档contains,您会发现它需要一些&Q作为参数。还有一些界限:where T: Borrow<Q>, Q: Hash + Eq. 我们可以忽略这Hash + Eq部分;它不会引起任何问题。

所以让我们专注于T: Borrow<Q>. 我们知道什么T是:&str. 所以让我们看看implBorrow什么&str文档。我们会发现许多通用 impl,其中重要的是(去除了一些噪音):

  • impl<T> Borrow<T> for T
  • impl<T> Borrow<T> for &T

&str因此,将我们的模式与右手模式匹配,我们得出结论&str,实现了 forBorrow<&str>Borrow<str>。所以我们Q可以是str例如。这意味着contains接收一个类型的参数&str(记住&Q上面的)。

capture然而,是类型String&capture是类型的表达式&String。每当在需要 a 的位置使用这样的表达式时&str,编译器就知道如何转换&String&str(deref coercion)。然而,在这种情况下,情况并不那么清楚,因为我们绕道而行Borrow。因此,我们必须显式地将 转换String&str. 有很多方法可以实现这一点,但是as_str()呢?所以 ...

工作解决方案

if refs.contains(capture.as_str()) {
    // ...
}
于 2016-08-25T15:56:58.670 回答