如何将字符串传递给HashSet包含?

ray*_*ray 3 string hashset rust borrowing

我想使用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
});
Run Code Online (Sandbox Code Playgroud)

这会导致此错误:

 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`
Run Code Online (Sandbox Code Playgroud)

如果我试试

refs.contains(&capture)
Run Code Online (Sandbox Code Playgroud)

然后我明白了

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) {
                                           ^~~~~~~~
Run Code Online (Sandbox Code Playgroud)

我很难过,我需要做某种类型的演员吗?

Luk*_*odt 10

说明

首先,让我们找出哪种类型refs.此时HashSet::new(),编译器无法判断您要将哪些内容放入集合中,因此类型尚不清楚.但是编译器在这一行中找到了它:

refs.insert(caps.at(2).unwrap());
Run Code Online (Sandbox Code Playgroud)

函数call(caps.at(2).unwrap())内的表达式返回一个&str.所以我们将&strs放入集合中,因此refs具有类型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,Borrow<&str>并且Borrow<str>已经实现.所以我们Q可以是str例如.这意味着contains接收类型的参数&str(记住&Q上面的).

capture但是,是类型String.&capture是一种类型的表达&String.每当这样的表达式被用于&str毫无疑问需要a的位置时,编译器就知道如何&String变成&str(deref强制).然而,在这种情况下,情况并不那么清楚,因为我们绕道而行Borrow.因此我们必须明确地将其转换String为a &str.有一种方法可以达到这个目的,但是怎么样as_str()?所以 ...

工作方案

if refs.contains(capture.as_str()) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)