如何将字符串传递给 HashSet 包含?
How do I pass a string to HashSet contains?
我想使用 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) {
^~~~~~~~
我很困惑,我需要做一些类型转换吗?
说明
首先,让我们找出refs
有什么类型。在HashSet::new()
点,编译器无法判断你要放入集合中的是什么类型,所以类型还不清楚。但是编译器在这一行中计算出来:
refs.insert(caps.at(2).unwrap());
函数调用里面的表达式(caps.at(2).unwrap()
)returns一个&str
。所以我们将 &str
s 放入集合中,因此 refs
具有类型 HashSet<&str>
。
如果您现在查看 documentation for contains
,您会发现它需要一些 &Q
作为参数。还有一些界限:where T: Borrow<Q>, Q: Hash + Eq
。我们可以忽略 Hash + Eq
部分;它不会造成任何问题。
所以让我们关注 T: Borrow<Q>
。我们确实知道 T
是什么:&str
。因此,让我们看看 Borrow
中的 impl
对于 &str
:documentation。我们会发现许多通用的 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
的位置使用这样的表达式时,编译器就知道如何将 &String
转换为 &str
(deref 强制)。然而,在这种情况下,情况并不那么清楚,因为我们绕过了 Borrow
特征。因此我们必须明确地将 String
转换为 &str
。有多种方法可以实现这一点,但是 as_str()
怎么样?所以...
工作解决方案
if refs.contains(capture.as_str()) {
// ...
}
我想使用 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) {
^~~~~~~~
我很困惑,我需要做一些类型转换吗?
说明
首先,让我们找出refs
有什么类型。在HashSet::new()
点,编译器无法判断你要放入集合中的是什么类型,所以类型还不清楚。但是编译器在这一行中计算出来:
refs.insert(caps.at(2).unwrap());
函数调用里面的表达式(caps.at(2).unwrap()
)returns一个&str
。所以我们将 &str
s 放入集合中,因此 refs
具有类型 HashSet<&str>
。
如果您现在查看 documentation for contains
,您会发现它需要一些 &Q
作为参数。还有一些界限:where T: Borrow<Q>, Q: Hash + Eq
。我们可以忽略 Hash + Eq
部分;它不会造成任何问题。
所以让我们关注 T: Borrow<Q>
。我们确实知道 T
是什么:&str
。因此,让我们看看 Borrow
中的 impl
对于 &str
:documentation。我们会发现许多通用的 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
的位置使用这样的表达式时,编译器就知道如何将 &String
转换为 &str
(deref 强制)。然而,在这种情况下,情况并不那么清楚,因为我们绕过了 Borrow
特征。因此我们必须明确地将 String
转换为 &str
。有多种方法可以实现这一点,但是 as_str()
怎么样?所以...
工作解决方案
if refs.contains(capture.as_str()) {
// ...
}