skip to Main Content

I need to use an object as keys for my map, therefore I extended the map class that stringifies the object passed, like so

class CoordMapper extends Map {
    set = (k: ISquareCoordinate, v: Array<ISquareCoordinate>) => {
        const stringifiedKey = JSON.stringify(k)
        return super.set(stringifiedKey,v)
    }

    get = (k: ISquareCoordinate) => {
        const stringifiedKey = JSON.stringify(k)
        return super.get(stringifiedKey)
    }
}

As far as I understand keys(), values() and entries() are generator methods, therefore I can do something like

* keys() {
   const keysArr = [...super.keys()]
   for (const key of keysArr){
      yield JSON.parse(key)
   }
}

But this causes me to load all the keys which I wish to avoid, is there a better way?

EDIT:
While Map does take in objects as keys but it only checks objects by reference. As an example

let newMap = Map()
const obj1 = {'a': 1, 'b' :2}
newMap.set(obj1, 123)
const copyObj1 = {...obj1}
console.log(newMap.get(obj1)) //returns 123
console.log(newMap.get(copyObj1)) //returns undefined

And i need the second console.log to return 123 aswell

2

Answers


  1. Rather than collecting all the parent values into an array, just iterate over them directly:

    * keys() {
       const parentKeyIterator = super.keys();
       for (const key of parentKeyIterator){
          yield JSON.parse(key)
       }
    }
    

    That way, the laziness of the iterator is retained: each time next() is called on your extended iterator, it will call next() on parentKeyIterator once, then reach your yield statement, and pause.

    Login or Signup to reply.
  2. Just in case someone stumble here in the future, there’s a stage-3 proposal which, if approved, would add syntactic sugar for iterators so that you can do something like this:

    class CoordMapper extends Map {
      *keys() {
        yield* super.keys().map(key => JSON.parse(key));
      }
    }
    

    Try it (this doesn’t work yet):

    console.config({ maximize: true });
    
    class CoordMapper extends Map {
      set(k, v) {
        return super.set(JSON.stringify(k), v)
      }
      get(k) {
        return super.get(JSON.stringify(k));
      }
      *keys() {
        console.log(super.keys())
        yield* super.keys().map(JSON.parse);
      }
    }
    
    const c = new CoordMapper();
    
    c.set({ foo: 'bar' }, 0);
    c.set({ baz: 42 }, 1);
    c.set({ qux: { lorem: 'ipsum' } }, [null, undefined]);
    
    for (const key of c.keys()) {
      console.log(key);
    }
    <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search