简体   繁体   English

如何使用盒子<String>作为带有 &amp;str 键的哈希图的查找键?

[英]How to use a Box<String> as a lookup key for a hashmap with &str keys?

My hashmap keys are expected to be of type &str , in particular &'static str , and I've received an owned Box<String> .我的 hashmap 键应该是&str类型,特别是&'static str ,我收到了一个拥有的Box<String>
How do I search my string against my hashmap?如何根据我的哈希图搜索我的字符串?

use std::collections::HashMap;

fn main() {
    let mut map: HashMap<&str, u32> = HashMap::new();
    let static_string = "a";
    map.insert(static_string, 5);

    let owned_boxed_string = Box::new(String::from("a"));

    map.get(owned_boxed_string); // mismatched type (ok)
    map.get(*owned_boxed_string); // mismatched type (ok)
    map.get(&*owned_boxed_string); // trait bound not satisfied (?)
} 

Let's look at the definition of HashMap::get() :我们来看看HashMap::get()的定义:

pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where
    K: Borrow<Q>,
    Q: Hash + Eq, 

In your code, K is &'static str and Q is deduced from each of the calls to get .在您的代码中, K&'static str并且Q是从对get每次调用中推导出来的。 In plain English, get() takes a reference to a type Q such that &'static str implements Borrow<Q> .在简单的英语中, get()引用类型Q使得&'static str实现Borrow<Q>

The rationale is that usually you will store keys of type String or the like, and you will search using values of type &str .基本原理是通常您将存储String或类似类型的键,并且您将使用&str类型的值进行搜索。 And naturally String implements Borrow<str> so you can do that.自然String实现Borrow<str>所以你可以做到这一点。

In your case, your key is not String but &'static str ... Take a look at the documentation for Borrow and look for what kind of Borrow<Q> is implemented by &'static str .在您的情况下,您的键不是String而是&'static str ... 查看Borrow的文档并查找&'static str实现的Borrow<Q>类型。 I can only see these two blanket implementations:我只能看到这两个全面的实现:

impl<'_, T: ?Sized> Borrow<T> for &'_ T
impl<T: ?Sized> Borrow<T> for T

The first one states that if your map keys are references to some type &K you can call get(k: &K) .第一个指出,如果您的地图键是对某种类型&K引用,您可以调用get(k: &K) The second one says that if your key is K you can call get(k: &K) .第二个说如果你的密钥是K你可以调用get(k: &K)

So for your particular case of &'static str they are realized as:因此,对于&'static str特殊情况,它们被实现为:

impl Borrow<str> for &'static str
impl Borrow<&'static str> for &'static str

From that you can deduce that your function is either get(k: &str) or get(k: &&str) .从中您可以推断出您的函数是get(k: &str)get(k: &&str) Here the easiest choice is the first one.这里最简单的选择是第一个。

Now, you may think that your last line ( map.get(&*owned_boxed_string); ) should work, because that value is of type &str , but it actually is not, it is of type &String .现在,您可能认为您的最后一行( map.get(&*owned_boxed_string); )应该可以工作,因为该值的类型为&str ,但实际上不是,它的类型为&String If HashMap::get() received a &str it would compile fine, but taking a Borrow<Q> , the compiler gets all confused and fails.如果HashMap::get()收到一个&str它会编译得很好,但是如果使用Borrow<Q> ,编译器就会感到困惑并失败。

TL; TL; DR;博士; : Add a type cast or a temporary typed variable: :添加类型转换或临时类型变量:

map.get(&*owned_boxed_string as &str);  //ok
map.get(&owned_boxed_string as &str);   //also ok

let s: &str = &*owned_boxed_string;
map.get(s);
let s: &str = &owned_boxed_string;
map.get(s);

Although an easier solution (thanks to @harmic for the comment below) is to use String::as_str() that will take care of as many derefs as required and just return the necessary &str :尽管更简单的解决方案(感谢@harmic 提供下面的评论)是使用String::as_str() ,它将根据需要处理尽可能多的 deref 并只返回必要的&str

map.get(owned_boxed_string.as_str());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM