9

[10,"20",null,"1","bar","-2",-3,null,5,"foo"]我正在尝试对可以是数字或字符串值(例如)的混合值的数组进行排序。我怎样才能对这个数组进行排序,这样

  • null值总是放在最后(不管排序顺序,参见 jsFiddle)
  • 负数被正确排序(即它们小于正数并且在它们之间正确排序)

? 我用详细的数字和字符串示例(使用和选项)制作了一个jsFiddle,但将在下面粘贴我的排序算法的数字版本作为起点。localeComparenumeric

// Sorting order
var order = "asc"; // Try switching between "asc" and "dsc"

// Dummy arrays
var numericArr = [10,20,null,1,-2,-3,null,5];

// Sort arrays
$(".output1").append(numericArr.toString());
numericArr.sort(sortByDataNumeric);
$(".output2").append(numericArr.toString());

// Numeric sorting function
function sortByDataNumeric(a, b, _order) {

    // Replace internal parameters if not used
    if (_order == null) _order = order;

    // If values are null, place them at the end
    var dflt = (_order == "asc" ? Number.MAX_VALUE : -Number.MAX_VALUE);

    // Numeric values
    var aVal = (a == null ? dflt : a);
    var bVal = (b == null ? dflt : b);
    return _order == "asc" ? (aVal - bVal) : (bVal - aVal);
}

我的字符串排序算法(参见jsFiddle)的问题是我找不到始终将null值放在最后的方法,并且负值在它们自身内部没有正确排序(例如 -3 应该小于 -2)

编辑

为了回答评论,我希望[10,"20",null,"1","bar","-2",-3,null,5,"foo"]排序[-3,"-2","1",5,10,"20","bar","foo",null,null]

4

4 回答 4

11

您应该首先检查是否有任何一个值null并返回相反的值。


附带说明:

对于您的默认_order值,您应该检查参数是否是,undefined而不是将其值与null. 如果您尝试直接比较未定义的内容,您将收到参考错误:

(undefinedVar == null) // ReferenceError: undefinedVar is not defined

相反,您应该检查变量是否未定义:

(typeof undefinedVar == "undefined") // true

此外,将比较函数包装在闭包中而不是依赖于全局顺序变量可能是一个更好的主意。

有时像:

[].sort(function(a, b){ return sort(a, b, order)})

这样,您可以按实例级别进行排序。


http://jsfiddle.net/gxFGN/10/

JavaScript

function sort(a, b, asc) {
    var result;

    /* Default ascending order */
    if (typeof asc == "undefined") asc = true;

    if (a === null) return 1;
    if (b === null) return -1;
    if (a === null && b === null) return 0;

    result = a - b;

    if (isNaN(result)) {
        return (asc) ? a.toString().localeCompare(b) : b.toString().localeCompare(a);
    }
    else {
        return (asc) ? result : -result;
    }
}
于 2013-09-30T22:33:53.030 回答
2
function sortByDataString(a, b) {
    if (a === null) {
        return 1;
    }
    if (b === null) {
        return -1;
    }
    if (isNumber(a) && isNumber(b)) {
        if (parseInt(a,10) === parseInt(b,10)) {
            return 0;
        }
        return parseInt(a,10) > parseInt(b,10) ? 1 : -1;
    }
    if (isNumber(a)) {
        return -1;
    }
    if (isNumber(b)) {
        return 1;
    }
    if (a === b) {
        return 0;
    }
    return a > b ? 1 : -1;
}

在这里摆弄:http: //jsfiddle.net/gxFGN/6/

我省略了 order 参数,但如果需要,您始终可以在最后反转数组。

于 2013-09-30T19:54:07.060 回答
1

用这个:

function typeOrder(x) {
    if (x == null)
        return 2;
    if (isNaN(+x))
        return 1;
    return 0;
}
function sortNumber(a, b) {
    a = parseInt(a, 10); b = parseInt(b, 10);
    if (isNaN(a) || isNaN(b))
        return 0;
    return a - b;
}
function sortString(a, b) {
    if (typeof a != "string" || typeof b != "string")
       return 0;
    return +(a > b) || -(b > a);
}

order = order == "dsc" ? -1 : 1;
numericArr.sort(function(a, b) {
    return order * ( typeOrder(a)-typeOrder(b)
                     || sortNumber(a, b)
                     || sortString(a, b)
                   );
});

更新小提琴

于 2013-09-30T20:45:15.450 回答
0

我很确定你的问题是一个红鲱鱼......你过去的抽象函数sort没有得到第三个参数(在你的情况下_order)。所以在你的情况下,总是会这样undefined

请牢记这一点,重新考虑您的代码,看看您会得到什么。

您指定的数组完全是数字的,因此您的排序应该正常工作,尽管正如其他评论者所建议的那样,如果您的数组以字符串值结束(即“10”、“-7”等),您将需要 parseInt 和测试在进行比较之前为 isNaN 。

于 2013-09-30T19:09:05.763 回答