Closed dy closed 4 years ago
This is interesting, but I wonder at this point if you really need two sets, when array.includes
works the same as set.has
, the array.push
works faster than set.add
, as no validation is needed, and you wouldn't even need to new Set(b)
.
However, if you're happy with the two sets, I'm happy to merge this.
Example of how I'd write it:
module.exports = (parent, a, b, end = null) => {
let aidx = [], i = 0, cur, next, bi
while (bi = a[i++]) b.includes(bi) ? (aidx.push(bi), cur = cur || bi) : parent.removeChild(bi)
cur = cur || end, i = 0
while (bi = b[i++]) {
next = cur.nextSibling
// skip
if (cur == bi) cur = next
else {
// swap
if (b[i] === next && aidx.includes(bi)) cur = next
// insert
parent.insertBefore(bi, cur)
}
}
return b
}
P.S. either ways, accessing an out of bound index would forever de-optimize the array. The entry array a
can probably be de-optimized without issues, but I'd really consider using the b.length
instead of looping via b[i++]
, as the b
is the array that you return, and the faster it works, the better.
I noticed that a.includes
or b.includes
performs poorly on 10k swap/create, compared to Set, also that forces a
to be an Array, not NodesList.
One ridiculous discovery though is that aidx
is not needed, so it allowed reducing size to 177b with better performance/memory. The gained space can be used for append-only shortcut (prominent case!), but I wonder if there's a way to generalize it.
UPDATE. Switched to no Sets inflate-first strategy (that turns out to be even more compact - 168bytes), but added fast shortcuts for the saved space. Now 208b, but performs better.
this is actually how I would write this:
module.exports = (parent, a, b, end = null) => {
let aLength = a.length, bLength = b.length, i = 0, cur, next, bi;
while (i < aLength && i < bLength && a[i] === b[i]) i++;
if (i == aLength)
while (i < bLength)
parent.insertBefore(b[i++], end);
else {
// in no circumstances a[i] can be falsy here
cur = a[i];
while (i < bLength) {
bi = b[i++];
next = cur ? cur.nextSibling : end;
if (cur == bi)
cur = next;
else if (i < bLength && b[i] == next) {
parent.replaceChild(bi, cur);
cur = next;
}
else
parent.insertBefore(bi, cur);
}
while (cur != end) {
// in no circumstances `cur` can be falsy here ...
next = cur.nextSibling || end;
// ... or this would've failed, if `cur` was falsy
parent.removeChild(cur);
cur = next;
}
}
};
191 bytes spect with better memory/performance profile, deflate-first strategy.