Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve value from Hashmap using partial key

Tags:

hashmap

rust

I have a HashMap with key type (i64,usize)

Suppose I have an use case to retrieve data from this HashMap using only first part of Key tuple.

For example I have sample data like this

(-1, 1): "1st -1 Resident", 
(1, 1): "1st 1 Resident", 
(1, 0): "Oth 1 Resident", 
(1, 2): "2nd 1 Resident", 
(-1, 2): "2nd -1 Resident", 
(-1, 0): "Oth -1 Resident"

I want to retrieve or operate on all data with -1 as the first entry of key tuple. Or in terms of the above example, all residents of -1. I'm currently doing this, looping over all entries in Hashmap and manually checking the first part of key tuple.

use std::collections::HashMap;

fn main(){
    let mut hmap: HashMap<(i64,usize), &str> = HashMap::new();
    hmap.insert((-1,0), "Oth -1 Resident");
    hmap.insert((-1,1), "1st -1 Resident");
    hmap.insert((-1,2), "2nd -1 Resident");
    
    hmap.insert((1,0), "Oth 1 Resident");
    hmap.insert((1,1), "1st 1 Resident");
    hmap.insert((1,2), "2nd 1 Resident");

    for (k,v) in &hmap {
        if k.0 == -1 {
            println!("{:?}",v);
        } 
    }
}

Is there any better way to do this? Here is the link to my current work (playground link)

like image 660
Sreyas Avatar asked Mar 12 '26 14:03

Sreyas


1 Answers

Is there any better way to do this?

Not with a hashmap, as an entry is localised by a hash of the entire key there is no partial matching possible.

However it would be possible using a BTreeMap: a BTreeMap's entries are positioned based on ordering of the keys, so you can iterate a subset based off of a range, which also works as a prefix match / search (that is why e.g. database indexes use btrees by default, it provides for more flexible querying than hashes).

Here you can request the range starting at (-1, usize::MIN) inclusive and ending at (0, usize::MIN) exclusive, and it'll give you all the entries whose key starts with -1.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2a78568fa2870afa949919075d7c3579

use std::collections::BTreeMap;

fn main(){
    let mut hmap: BTreeMap<(i64,usize), &str> = BTreeMap::new();
    hmap.insert((-1,0), "Oth -1 Resident");
    hmap.insert((-1,1), "1st -1 Resident");
    hmap.insert((-1,2), "2nd -1 Resident");
    
    hmap.insert((1,0), "Oth 1 Resident");
    hmap.insert((1,1), "1st 1 Resident");
    hmap.insert((1,2), "2nd 1 Resident");

    for (k,v) in hmap.range((-1, usize::MIN)..(0, usize::MIN)) {
        println!("{k:?} {v}");
    }
}

output:

(-1, 0) Oth -1 Resident
(-1, 1) 1st -1 Resident
(-1, 2) 2nd -1 Resident
like image 161
Masklinn Avatar answered Mar 15 '26 09:03

Masklinn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!