Something like this perhaps?
Javascript
// swap two elements in an array by their indexes a and b and
// return an array of the swapped coordinates.
function swap(arr, a, b) {
// assign the value at index a to temp
var temp = arr[a];
// assign the value at index b to index a
arr[a] = arr[b];
// assign the value of temp to the value at index b
arr[b] = temp;
// coordinates of move
return [a, b];
}
// return an array of moved coordinates
function minMoves(arr1, arr2) {
// take a shallow copy of arr2 so that the original is not modified
arr2 = arr2.slice();
// apply a function against an accumulator (moves) for each value of
// the array (arr1) (from left-to-right)
return arr1.reduce(function (moves, item, index) {
// if the values of each array at the index are not the same
if (item !== arr2[index]) {
// swap the current indexed element of arr2 with the value of
// the correct element as indexed in arr1. Add the moved
// coordinates to the beginning of the accumulator
moves.unshift(swap(arr2, index, arr2.lastIndexOf(item)));
}
// return the accumulater for the next iteration
return moves;
}, []);
}
var before = [1, 5, 6, 3, 2, 4, 7, 8, 9, 0],
test = before.slice(),
after = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
moves = minMoves(before, after);
console.log('moves: ' + JSON.stringify(moves));
moves.forEach(function(move) {
swap(test, move[0], move[1]);
});
console.log('Should be ordered nicely: ' + JSON.stringify(test));
Output
moves: [[3,5],[2,5],[1,4]]
Should be ordered nicely: [1,2,3,4,5,6,7,8,9,0]
On jsFiddle
This is what I would do, it is not based on any research of algorithms that have been proven optimal.
And here is the code using your arrayMove
method instead of swap
Javascript
function arrayMove(array, from, to) {
return array.splice(to, 0, array.splice(from, 1)[0]);
}
// return an array of moved coordinates
function minMoves(arr1, arr2) {
// take a shallow copy of arr2 so that the original is not modified
arr2 = arr2.slice();
// apply a function against an accumulator (moves) for each value of
// the array (arr1) (from left-to-right)
return arr1.reduce(function (moves, item, index) {
var last;
// if the values of each array at the index are not the same
if (item !== arr2[index]) {
// swap the current indexed element of arr2 with the value of
// the correct element as indexed in arr1. Add the moved
// coordinates to the beginning of the accumulator
last = arr2.lastIndexOf(item);
arrayMove(arr2, last, index);
moves.unshift([index, last]);
}
// return the accumulater for the next iteration
return moves;
}, []);
}
var before = [1, 5, 6, 3, 2, 4, 7, 8, 9, 0],
test = before.slice(),
after = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
moves = minMoves(before, after);
console.log('moves: ' + JSON.stringify(moves));
moves.forEach(function(move) {
arrayMove(test, move[0], move[1]);
});
console.log('Should be ordered nicely: ' + JSON.stringify(test));
Output
moves: [[3,4],[2,5],[1,4]]
Should be ordered nicely: [1,2,3,4,5,6,7,8,9,0]
On jsFiddle
Finally a jsPerf to compare the two methods.