Reputation: 49
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?
Upvotes: 0
Views: 1399
Reputation: 1836
Maps retain the insertion order of their keys:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
Any iterator methods for Maps will iterate over the keys in insertion order.
Objects do not guarantee that the insertion order of their keys is preserved:
Does JavaScript guarantee object property order?
Neither Maps nor Objects track update order. You'd need a custom solution for this, probably using a Proxy.
Upvotes: 0
Reputation: 35243
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))
Upvotes: 2