Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript map with composite keys

In JavaScript I want to store values to compound keys, similar to a C# dictionary with a tuple as key. This is where I came across the Map class. However, it does not seem to work quite as well as I would like it to. Here's my current approach:

var test = new Map();

test.set({a: 1, b: 1}, 'Bla');
test.set({a: 5, b: 7}, 'Blub');

test.get({a: 1, b: 1}); // ==> Returns undefined; would expect 'Bla'

I guess, that this has something to do that both objects with {a: 1, b: 1} have a different memory address and therefore are the same, but not identical. The Dictionary class in c# uses a hash function in background. Is there something similar in JS? Or a much easier approach?

My real key object consistst of three strings.

like image 922
André Reichelt Avatar asked Apr 15 '20 14:04

André Reichelt


People also ask

What is map keys in JavaScript?

JavaScript Map keys() method The JavaScript map keys()method returns an object of new Mapiterator. This object contains the key for each element. It maintains insertion order.

What are the parameters of map in JavaScript?

map1.has (k); Parameters: k - Key of the element to checked Returns: true if the element with the specified key is present or else returns false. 3. Map.prototype.get () – It returns the value of the corresponding key. 4. Map.prototype.delete () – It delete’s both the key as well as a value from the map. 5.

What is a JavaScript map object?

Summary: in this tutorial, you will learn about the JavaScript Map object that maps a key to a value. Prior to ES6, when you need to map keys to values, you often use an object, because an object allows you to map a key to a value of any type. However, using an object as a map has some side effects:

What is the keys () method in map ()?

The keys () method returns a new Iterator object that contains the keys for each element in the Map object in insertion order. A new Map iterator object.


2 Answers

Your analysis is correct. It works like this because in Javascript you usually operate primitive objects that don't have all this hashing behavior attached to them out of the box. Nothing stops you from implementing your own Dictionary with hash function in background though

class Dictionary {
  map = {}

  constructor(hashFunction) {
    this.hashFunction = hashFunction
  }

  set(key, item) {
    this.map[this.hashFunction(key)] = item
  }

  get(key) {
    return this.map[this.hashFunction(key)]
  }

  delete(key) {
    delete this.map[this.hashFunction(key)]
  }
}

const dict = new Dictionary((keyObject) => JSON.stringify(keyObject))
dict.set({ a: 1, b: 2 }, 'hello')
console.log(dict.get({ a: 1, b: 2 })) // hello

As to what to use, Map or object, the difference between Map and object is simply that object only supports string keys (also Symbols but irrelevant right now) while Map supports any value at a cost of using more resources, less compatibility with old browsers, and it's generally less handy to use than object (and also stops GC from cleaning out those objects you use as keys). That said, object is your choice here

like image 196
Max Avatar answered Oct 25 '22 12:10

Max


{} this operator will create a new object every time; and a new object will have a different object refenece each time; if you save the object reference and use that for multiple operation its ok; but since you are trying to use a new object refence every time it won't work; you may either use a primitive type as key, or same object reference like the snippet below

//approach 1 using same object reference
var test = new Map();
var obj = {a: 1, b: 1};
test.set(obj, 'Bla');
test.set({a: 5, b: 7}, 'Blub');
let result = test.get(obj); 
console.log(result);

// aproach 2 using JSON.stringify
test = new Map();
test.set(JSON.stringify({a: 1, b: 1}), 'Bla');
test.set({a: 5, b: 7}, 'Blub');
result = test.get(JSON.stringify({a: 1, b: 1})); 
console.log(result)
like image 21
Mhmdrz_A Avatar answered Oct 25 '22 14:10

Mhmdrz_A