JavaScript:重新排序数组

时间:2014-11-28 22:20:16

标签: javascript arrays

关于处理拼接时的问题(包括Move an array element from one array position to another),我读了几个关于问题的答案,但我无法解决我的问题。

我正在尝试以特定模式重新排序数组。我们假设模式是所有负数应该是数组的,所有 postive 数字应该是正确的数组。如果有的话,负数和正数应该用分隔。 维护订单非常重要

Sample Input   = [3,0,2,-1,0,-3]
Desired Output = [-1,-3,0,0,3,2]

这是我写的代码

function reorderArray(inputArray) {
origLength = inputArray.length
var indexZero = -1;
  for (var i = 0; i < origLength; i++) {
    if (inputArray[i] > 0) {
        inputArray.push(inputArray[i]);
        inputArray.splice(i, 1);
    } else if (indexZero == -1 && inputArray[i] == 0) {
        indexZero = i;
    } else if (indexZero != -1 && inputArray[i] < 0) {
        inputArray.splice(indexZero, 0, inputArray.splice(i, 1))
        indexZero++;
    }
  }
alert(inputArray);
}

我在第一步遇到问题,我试图在数组后面移动所有正数,因为重新索引。我无法从最后一个索引开始,因为这意味着丢失订单而我不能使用 i - ,因为它会无限运行。

任何有关如何使我的代码工作的帮助将不胜感激。另外,如果有一种比splice更有效的替代方案,那也是受欢迎的。

感谢。

3 个答案:

答案 0 :(得分:2)

var input = [3,0,2,-1,0,-3];

var copy = input.slice(0); // you need an original array copy since you need to
                           // refer to it to maintain the original order

input.sort(function(a, b) {
    var sign_a = Math.sign(a),
        sign_b = Math.sign(b);

    if (sign_a != sign_b) {
        return sign_a - sign_b;
    }

    return copy.indexOf(a) - copy.indexOf(b);
});

console.log(input);

JSFiddle:http://jsfiddle.net/w2g195fy/2/

因此,您首先按符号比较数字,然后通过比较原始数组中的位置来保证排序的稳定性。后者重要,因为Array.prototype.sort() 无法保证保持稳定。

另一个重要说明:此特定实现的复杂性(从比较数量的角度来看)是O(N^2 * logN),如果您有大型原始数组,这可能是不可接受的。

另一个重要提示:如果您的输入数组有重复值,它将不起作用。

这是一个天真的实现,可以使用重复项:

var input = [1, -1, 2, 0, -2, 3, 0, -3, -4, 4, 0];

var groups = input.reduce(function(result, item) {
    result[Math.sign(item)].push(item);
    return result;
}, {'-1': [], 0: [], 1: []});

var result = groups['-1'].concat(groups[0]).concat(groups[1]);

console.log(result)

这是我能想到的最有效的(从内存和比较数量的角度来看 - 它是O(N))解决方案:

var input = [1, -4, 2, 0, -2, 3, 0, -3, -4, 4, 0];

var result = [];

for (var sign = -1, len = input.length; sign <= 1; ++sign) {
    for (var i = 0; i < len; ++i) {
        if (Math.sign(input[i]) == sign) {
            result.push(input[i]);
        }
    }
}

console.log(result);

http://jsfiddle.net/pbmw4dtt/

答案 1 :(得分:1)

使用sort执行此操作的另一种方法:

[3,0,2,-1,0,-3].map(function () { return arguments; }).sort(function (a, b) {
    var aNum = a[0],
        bNum = b[0],
        bothNegative = aNum < 0 && aNum < 0,
        bothPositive = aNum > 0 && bNum > 0;

    if (bothNegative || bothPositive) return a[1] - b[1];
    return aNum - bNum;

}).map(function (arr) { return arr[0]; });

保留初始订单,但现在它们分为3组。否定,零和积极。

答案 2 :(得分:0)

这也可以是一个解决方案:

var input = [3,0,2,-1,0,-3].join('+');
var output = input.match(/-\d+/g).concat( input.match(/0/g) ).concat( input.match(/(^|\+)[1-9]\d*/g) ).map(parseFloat);

Fiddle

由于最后一个数组sort(可以省略),它比map慢,但想法可能有用。