-
-
Save LeaVerou/2881cc634df29c9d1c89fcb965f699f0 to your computer and use it in GitHub Desktop.
function insert(obj, {before, property, value}) { | |
let found, temp = {}; | |
// Delete all properties from before onwoards and save them in temp | |
for (let p in obj) { | |
if (p === before) { | |
found = true; | |
} | |
if (found) { | |
temp[p] = obj[p]; | |
delete obj[p]; | |
} | |
} | |
// Add new property | |
obj[property] = value; | |
// Re-add removed properties | |
for (let p in temp) { | |
obj[p] = temp[p]; | |
} | |
} |
function insert(obj, {before, property, value}) { | |
let found, temp = {}; | |
// Delete all properties from before onwoards and save them in temp | |
for (let p in obj) { | |
if (p === before) { | |
found = true; | |
} | |
if (found) { | |
temp[p] = obj[p]; | |
delete obj[p]; | |
} | |
} | |
// Add new property and re-add removed properties | |
Object.assign(obj, {property: value, ...temp}); | |
} |
function insert(obj, {before, property, value}) { | |
// Create a copy of entries and add the new property in place | |
let entries = Object.entries(obj); | |
let i = entries.findIndex(a => a[0] === before); | |
entries.splice(i, 0, [property, value]); | |
// Delete all obj properties | |
for (let p in obj) { | |
delete obj[p]; | |
} | |
// Re-add with the new one | |
Object.assign(obj, Object.fromEntries(entries)); | |
} |
@bgotink's last method is the fastest in every browser, I would have expected it to be slower since it intermingles deletions and additions, but it isn't the case. One loop wins (fewer allocations, I suppose).
Yes, maybe it's not just the memory part of the allocation and gc, and the fact that overall fewer ops are performed, but also the overhead of object processing via hidden classes - still, good call suspecting that deletes/appends in quick succession might also thrash the hidden classesi
@monfera This looks like this is your bread and butter... Would you have an idea of how to draw useful ticks in log space? I suppose I could find it if I think hard enough about it, but if there's a standard algorithm / lib for that it would save me some time and effort...
@pygy Assuming that all values are positive, you could use a d3.scaleLog
, a minimal example is here (though D3 v3) or a more complete, up to date one is here
If some values are zero, you can apply the trick of adding one to all values, but then subtracting one when formatting the axis tick value.
The benefit is that you can use D3 to generate the axis, the tick values, and the ticks (and/or grid lines) with the tick labels, which can then be channeled into SVG or HTML elements.
@monfera many thanks. I'd rather avoid pulling up d3 as a dep, I'll pilfer^Wstudy https://github.com/d3/d3-scale/blob/master/src/log.js for inspiration :-)
@pygy rolling your own code not fundamentally difficult, but finding the somewhat optimal set of tick values (so they're nice round numbers, and not too many ticks and not to few) and scale nicing etc. can get labor intensive, has edge cases too. Btw. there's no need to import the entirety of D3; it's enough to import d3-scale
, although the last time I checked, one still ends up with color palette arrays etc. which you wouldn't use. Therefore even d3-scale
is very large if you need it for just one cartesian scale. Not sure if Svelte-style JS treeshaking can get rid of the palettes etc. now, I think, worth a try, interested if you do that.
Slightly modified version of 2:
Personally I find this slightly easier to parse, the
Object.assign(obj, {[property]: value, ...temp})
took me a couple of reads to get right.Or an alternative with a single loop:
This is my favourite, a single loop makes this pretty straightforward, but again that's personal preference.