mirror of
https://github.com/DeviceFarmer/stf.git
synced 2026-04-18 16:23:28 +02:00
72 lines
1.6 KiB
JavaScript
72 lines
1.6 KiB
JavaScript
function existenceMap(array) {
|
|
var map = Object.create(null)
|
|
for (var i = 0, l = array.length; i < l; ++i) {
|
|
map[array[i]] = 1
|
|
}
|
|
return map
|
|
}
|
|
|
|
// Returns a list of operations to transform array a into array b. May not
|
|
// return the optimal set of operations.
|
|
module.exports = function patchArray(a, b) {
|
|
var ops = []
|
|
|
|
var workA = [].concat(a)
|
|
, inA = Object.create(null)
|
|
, itemA
|
|
, cursorA
|
|
|
|
var inB = existenceMap(b)
|
|
, posB = Object.create(null)
|
|
, itemB
|
|
, cursorB
|
|
|
|
// First, check what was removed from a.
|
|
for (cursorA = 0; cursorA < workA.length;) {
|
|
itemA = workA[cursorA]
|
|
|
|
// If b does not contain the item, surely it must have been removed.
|
|
if (!inB[itemA]) {
|
|
workA.splice(cursorA, 1)
|
|
ops.push(['remove', cursorA])
|
|
}
|
|
// Otherwise, the item is still alive.
|
|
else {
|
|
inA[itemA] = true
|
|
cursorA += 1
|
|
}
|
|
}
|
|
|
|
// Then, check what was inserted into b.
|
|
for (cursorB = 0; cursorB < b.length; ++cursorB) {
|
|
itemB = b[cursorB]
|
|
|
|
// If a does not contain the item, it must have been added.
|
|
if (!inA[itemB]) {
|
|
workA.splice(cursorB, 0, itemB)
|
|
ops.push(['insert', cursorB, itemB])
|
|
}
|
|
|
|
posB[itemB] = cursorB
|
|
}
|
|
|
|
// At this point, workA contains the same items as b, but swaps may
|
|
// be needed.
|
|
for (cursorA = 0; cursorA < workA.length;) {
|
|
itemA = workA[cursorA]
|
|
var posInB = posB[itemA]
|
|
|
|
if (posInB === cursorA) {
|
|
cursorA += 1
|
|
}
|
|
else {
|
|
var temp = workA[posInB]
|
|
workA[posInB] = itemA
|
|
workA[cursorA] = temp
|
|
ops.push(['swap', cursorA, posInB])
|
|
}
|
|
}
|
|
|
|
return ops
|
|
}
|