我正在尝试对值数组进行排序,这些值可以是数值或字符串值的混合(例如[10,"20",null,"1","bar","-2",-3,null,5,"foo"]
)。如何对此数组进行排序
null
值始终位于最后(无论排序顺序如何,请参阅jsFiddle)?我使用详细的数字和字符串示例(使用localeCompare
和numeric
选项)创建了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]
答案 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)})
这样您就可以按实例级别进行排序。
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)
);
});
答案 3 :(得分:0)
我很确定你的问题是一个红色的鲱鱼...你进入sort
的抽象函数没有得到第三个参数(在你的情况下_order
)。所以在你的情况下,总是undefined
。
请仔细考虑您的代码并查看您的代码。
您指定的数组完全是数字,因此您的排序应该正常工作,但正如其他评论者所建议的那样,如果您的数组最终结束了字符串值(即“10”,“ - 7”等),您将需要parseInt并在进行比较之前测试isNaN。