Search for a value in a HashMap

How is it possible to search for a value in a HashMap structor and receive multiple results if available.

Thanks for any hint.

Maybe use a combination hashmap’s .entries() to obtain an iterator and then use Iter.filter on that with a suitable predicate function to return an iterator of the matching values.

1 Like

OK, thank you.
Finally I came up with that solution, maybe this could be helpful to others, as well.

import Debug “mo:base/Debug”;
import Principal “mo:base/Principal”;
import HashMap “mo:base/HashMap”;
import Nat “mo:base/Nat”;
import Hash “mo:base/Hash”;
import Result “mo:base/Result”;
import Iter “mo:base/Iter”;
import List “mo:base/List”;

actor {

type TokenIndex = Nat;
type NextTokenIndex = Nat;
type Result<Ok, Err> = {#ok : Ok; #err : Err};

var next : NextTokenIndex = 0;

stable var registryEntries : [(TokenIndex, Principal)] = ;
let registry : HashMap.HashMap<TokenIndex, Principal> = HashMap.fromIter<TokenIndex, Principal>(registryEntries.vals(), 10,Nat.equal, Hash.hash);

public shared ({caller}) func mint() : async Result<(), Text> {
// tis is not working im 0.8.4 I think so !
registry.put(next, caller);
next += 1;
return #ok;
};

public shared ({caller}) func getTokenFromCaller (): async List.List {
var listOfTokenIndex = List.nil();

for ((k,v) in registry.entries()) {
  //Debug.print("> "#debug_show(v)#" == "#Principal.toText(caller));
  if( v == caller){
    listOfTokenIndex := List.push(k,listOfTokenIndex);
  };
};
return listOfTokenIndex;

};

// check your HashMap
public func checkRegistry (): async [(Nat, Principal)] {
return Iter.toArray<(Nat, Principal)>(registry.entries());
};

system func preupgrade() {
// uncomment this for testing
//Debug.print(“test”);
registryEntries := Iter.toArray(registry.entries());
};

system func postupgrade() {
registryEntries := ;
};
}

1 Like

This is more of a data structures/algorithms solution, but if you want efficient value lookup you might want a second <V, K>HashMap that is inverses your <K,V> HashMap, with the same data, just with the values becoming the keys and visa-versa.

Double the space taken up, but now you have instant lookups by value.

1 Like

Look ups for HashMaps are instant by value but not by key? I thought it would be the other way around.

Only if you have two of them <a,b> and <b,a>.

The trick here is that a lot of times b is an object and you are going to have to come up with a hash function and equality function for your object.

You may also want to consider using TrieMaps instead since they are much more memory efficient. See: NFTAnvil IC network tests report

2 Likes

Thanks to all answers, I think to write the example - implemented as Trie Element - would be good exercise fĂĽr me.

Maybe this is relevant: GitHub - aviate-labs/bimap.mo: Generic Bijective Maps in Motoko

2 Likes

I test all cases for GitHub - aviate-labs/bimap.mo: Generic Bijective Maps in Motoko. It works very well. Just import it as a module then are ready to go. We use the library in our project: IC-XRP/bridge.mo at main · Itoka-DAO/IC-XRP · GitHub