0

In javascript, is there a data structure that tracks insertion/update order? for instance, if you have:

map[a]=1
map[b]=2
map[c]=3

I would want to get the keys in order a,b,c but if I had

map[a]=1
map[b]=2
map[c]=3
map[b]=4

I would want the keys in order a,c,b since b was last updated.

I'm currently doing this with a js object and a sorted list to track update order. Is there a better way to do this?

name
  • 29
  • 4
  • I don't think there is something out of the box, so the best way is probably either asking to Google or doing it yourself as you're doing currently! – sjahan Feb 02 '21 at 15:35
  • Do you have an actual problem? If so add a [mcve], otherwise asking for an opinion ("is there a better way") is off-topic. – Andreas Feb 02 '21 at 15:36
  • So, b comes before c but not a because it was last updated. But initial insertion of a,b,c doesn't put c before b because it was last inserted. Your description is unclear. I'm voting to close because of this. Please try to give a real world use cases of a problem to solve. Contrived examples rarely help. The closest implementation of what you've described is a linked-list. – Randy Casburn Feb 02 '21 at 15:52

1 Answers1

2

You could create a Proxy object with a trap for set. Use a set to keep track of all the keys in the object. Every time you set a property, you can delete the key from the set before adding it. This ensures that the key just updated is always enumerated at the end.

A Set is used because, integer-like keys are enumerated before the string keys, irrespective of the order they are inserted. A set will keep the order of insertion. As suggested by @Kaiido, you can add an ownKeys trap. When the keys of the object are requested, then will be returned from the Set and the keys will be returned in the order of the Set.

const createHandler = (keys = new Set) => ({
  set(obj, prop, value) {
    keys.delete(prop);
    keys.add(prop);
    return Reflect.set(...arguments)
  },
  ownKeys(obj) {
    return Array.from(keys)
  }
})

const map = new Proxy({}, createHandler())

map.a = 1,
map.b = 2;
map[1] = "integer-like key"

console.log(Object.keys(map))

map.c = 3;
map.b = 5

console.log(Object.keys(map))
adiga
  • 34,372
  • 9
  • 61
  • 83
  • I think that using `ownKeys` you could also handle numeric keys: https://jsfiddle.net/0u9qzLaw/ – Kaiido Feb 03 '21 at 07:10
  • 1
    @Kaiido Thanks, I have updated the answer. I added a factory function for creating the handler to avoid polluting the scope and make it easy for multiple objects of this type to be created. – adiga Feb 03 '21 at 07:40