Is it possible to use String tuples for keys, &str tuples for lookups in Maps?


#1

I’m trying to create a map which uses tuples of String as the keys, but use &str to do the lookups for efficiency, but I can’t figure a way to do it:

Playground: https://is.gd/gqI8zL

let mut m: BTreeMap<(String,String),String> = BTreeMap::new();

...
let q = ("foo","bar");
m.get(&q);

I’ve tried creating structs with String elements and ‘&str’ elements and implementing Borrow, but I haven’t been able to work that out.

I’ve got a workaround, which is just to have a map of maps for each String in the tuple, but is there a better solution?

-Tony


#2

Right, your struct needs a concrete tuple that Borrow can return a reference to, and that tuple needs to borrow &strs from your own Strings. I haven’t tried to work this out, but the rental crate might be just what you need for those gymnastics.


#3

Another option to consider is something like:

#[derive(PartialOrd, Ord, PartialEq, Eq)]
struct Key<'a> {
    first: Cow<'a, str>,
    second: Cow<'a, str>
}

fn main() {

   let mut map: BTreeMap<Key,String> = BTreeMap::new();    
   // forcing owned Strings here for illustration purposes
   map.insert(Key {first: "foo".to_string().into(), second: "bar".to_string().into()}, "baz".to_string());

   let q = Key {first: "foo".into(), second: "bar".into()};
   let v = map.get(&q);
}

#4

Thanks for the replies.

I have definitely run into the problem rental is trying solve before, so that is helpful to know about.

I had not thought about using Cow like that, it makes sense since it must implement Ord`Eq\Hashsimilarly to how you'd have to for therental` version.