Search code examples
rustbtreemap

How to lookup ranges from BTreeMap using slice patterns or vectors?


I have a BTreeMap where I store items using a two-tuple key, (String, Vec<i32>), so the type of map that stores integers is BTreeMap<(String, Vec<i32>), i32>.

How can I get ranges by using the first element in the two-tuple while ignoring the content of the Vector (alternatively a slice &[i32])?

A short example:

//use core::slice::SlicePattern;
use std::collections::BTreeMap;

fn main() {
    let mut m : BTreeMap<(String, Vec<i32>), i32> = BTreeMap::new();
    m.insert(("hello".to_string(), vec![12]), 34);
    m.insert(("hello".to_string(), vec![4]), 56);
    m.insert(("other".to_string(), vec![4]), 44);

    let res_first = m.get(&("hello".to_string(), vec![12]));
    println!("{:?}", res_first);

    // not working, and not intuitive range
    for (k, v) in m.range(("hello".to_string(), [])..=("g".to_string(), [])) {
        println!("key {:?}", k);
    }
}

Is there a way I can use a slice pattern or something to make the range query work with Vectors or slices?

or something like:

m.range(("hello".to_string(), [])..=("hello".to_string(), [RangeFull]))

My previous question got a good answer, but it only works for scalars and not Vector or slices.


Solution

  • You can do this much the same way, except that you need a range where the end is exclusive, since you can't (easily) express the maximum possible Vec<i32>. You can specify an empty Vec for both ends of the range, and use the next-"largest" string at the end of the range, which is just the same string with a nul character added. (Thanks Filipe for this idea.)

    m.range(("hello".to_string(), vec![])..("hello\0".to_string(), vec![]))
    

    (Playground)