如何比较字符串和数字值(尊重负值,null总是持续)?

时间:2013-09-30 18:49:29

标签: javascript sorting

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

  • null值始终位于最后(无论排序顺序如何,请参阅jsFiddle)
  • 负数正确排序(即它们小于正数且在它们之间正确排序)

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

// 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 个答案:

答案 0 :(得分:7)

您应首先检查两个值是否为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;
    }
}

答案 1 :(得分: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参数,但如果需要,你总是可以在最后反转数组。

答案 2 :(得分: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)
                   );
});

updated fiddle

答案 3 :(得分:0)

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

请仔细考虑您的代码并查看您的代码。

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