diff 2数组,其中项目只是重新排序

时间:2014-05-15 21:01:29

标签: javascript arrays algorithm sorting

鉴于两个数组arr1arr2两个具有相同的项目,但排序方式不同,如何制作一个列表,列出了arr1所需的项目移动操作次数最少匹配arr2

执行此操作的函数/算法应该接受我的两个数组作为唯一参数,并返回如下数组:

[
    [1,5],
    [3,0],
    [7,2]
]

上述数组将被解释为“将索引1处的项目移至索引5,然后将索引3处的项目移至索引0,最后将索引7处的项目移至索引2.”

通过项目移动操作,我的意思如下:

function arrayMove(array, from, to) {
    return array.splice(to, 0, array.splice(from, 1)[0]);
}

当项目从索引a移动到索引b时,索引a之后的项目“向下滑动”,因此索引为a + 1的项目现在具有索引{ {1}},当项目在索引a处重新添加时,具有b的项目将向上滑动,以便具有索引index >= b的项目现在具有索引b

随意提供您的算法JS或伪代码,任何帮助赞赏。

2 个答案:

答案 0 :(得分:1)

这与我edit distance problem有关。也许你可以利用Wagner-Fischer algorithm

答案 1 :(得分:1)

或许这样的事情?

的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));

输出

moves: [[3,5],[2,5],[1,4]]
Should be ordered nicely: [1,2,3,4,5,6,7,8,9,0] 

jsFiddle

这就是我要做的,它不是基于任何已被证明是最优的算法研究。

以下是使用arrayMove方法代替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));

输出

moves: [[3,4],[2,5],[1,4]]
Should be ordered nicely: [1,2,3,4,5,6,7,8,9,0] 

jsFiddle

最后用jsPerf比较两种方法。