【问题标题】:How do I pass a string to HashSet contains?如何将字符串传递给 HashSet 包含?
【发布时间】:2016-08-25 15:39:30
【问题描述】:

我想使用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) {
                                           ^~~~~~~~

我很难过,我需要做一些类型转换吗?

【问题讨论】:

  • 您可以添加// put stuff in refs 部分吗?这实际上或多或少对这个问题很重要。
  • 请添加一个完整的例子我们可以尝试编译。听起来你有一个HashSet&lt;&amp;str&gt; 而不是HashSet&lt;String&gt;,正如@LukasKalbertodt 所说,这取决于你如何初始化refs。
  • @LukasKalbertodt 我在插入字符串的地方添加了。所以我认为在 HashSet 初始化时我需要做的更多...
  • @ray no 初始化没问题,但找出一些事情很重要。看看我的回答就明白我的意思了:)

标签: string rust hashset borrowing


【解决方案1】:

说明

首先,让我们找出refs 的类型。在HashSet::new()这一点上,编译器无法判断你要放入集合中什么样的东西,所以类型还不清楚。但是编译器在这一行中计算出来:

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

函数调用 (caps.at(2).unwrap()) 中的表达式返回 &amp;str。所以我们将&amp;strs 放入集合中,因此refs 的类型为HashSet&lt;&amp;str&gt;。

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

所以让我们关注T: Borrow&lt;Q&gt;。我们知道T 是什么:&amp;str。所以让我们看看Borrow 中的impl 是什么&amp;str:documentation。我们会发现许多通用 impl,其中重要的是(去除了一些噪音):

  • impl&lt;T&gt; Borrow&lt;T&gt; for T
  • impl&lt;T&gt; Borrow&lt;T&gt; for &amp;T

所以模式匹配我们的&amp;str 与右手模式,我们得出结论,对于&amp;str,Borrow&lt;&amp;str&gt; 和Borrow&lt;str&gt; 已实现。例如,我们的Q 可以是str。这意味着contains 接收&amp;str 类型的参数(请记住上面的&amp;Q)。

capture 然而,是String 类型。 &amp;capture 是 &amp;String 类型的表达式。每当在毫无疑问需要&amp;str 的位置使用这样的表达式时,编译器就知道如何将&amp;String 转换为&amp;str(去引用强制)。然而,在这种情况下,情况并不那么清楚,因为我们绕开了Borrow 特征。因此,我们必须将String 显式转换为&amp;str。有很多方法可以实现这一点,但是as_str() 怎么样?所以...

工作解决方案

if refs.contains(capture.as_str()) {
    // ...
}

【讨论】:

    猜你喜欢
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-02
    相关资源
    最近更新 更多