如何按字典顺序和数字顺序对一组数字进行排序?
How to sort set of numbers both lexicographically and numerically?
我目前有一组字符串,它们都是数字和带有 + 或 - 的数字。例如:
1 , 1+, 1-, 2, 2+, 2-, 10
当我使用 JavaScript 的排序函数进行排序时,输出:
1、1+、1-、10、2、2+、2-
这是按字典顺序而不是数字顺序。有没有办法对此进行排序,以便数字以正确的方式(第一个列表)出现?我正在使用 ExtJS 商店,因此首选答案作为商店分类器,但普通 javascript 也可以。谢谢?
编辑:这不仅仅是对数字进行排序。
您可以使用 Array#sort
并将元素拆分为数字和其余部分,然后 return 差值或顺序差值。
var array = ['10', '2', '2+', '2-', '1', '1+', '1-'];
array.sort(function (a, b) {
var r = /\d+|\D+/g,
aa = a.match(r),
bb = b.match(r),
order = { '+': 1, '-': 2 };
return aa[0] - bb[0] || (order[aa[1]] || 0) - (order[bb[1]] || 0);
});
console.log(array);
var result=[];
result=array.map(function(n){
if(typeof n==='number') return n;
if(n[n.length-1]=='+'){
return parseInt(n.substring(0,n.length-1))
}
else if(n[n.length-1]=='-'){
return 0-parseInt(n.substring(0,n.length-1))
}
});
result.sort(function(a,b){return a-b})
假设您只想丢弃符号,那么您可以使用 parseInt 和 Array#sort 来获取数字顺序。
var data = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
var sortedData = data.sort(function(a,b){return parseInt(a)-parseInt(b);});
这些值几乎都是整数,因此根据 praseInt
比较它们将 几乎 让你到达那里。唯一缺少的是对具有相同整数部分的值的特殊处理,其中 x-
应该首先出现,然后是 x
,最后是 x+
:
function specialChar(s) {
c = s.substr(-1);
if (c == '+') {
return 1;
}
if (c == '-') {
return -1;
}
return 0;
}
function numCompare(a, b) {
aNum = parseInt(a);
bNum = parseInt(b);
cmp = aNum - bNum;
if (cmp != 0) {
return cmp;
}
// Integer parts are equal - compare the special char at the end
return specialChar(a) - specialChar(b);
}
arr = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
arr.sort(numCompare);
您可以像这样使用自定义排序函数:
var numbers = ['1', '1-', '1+', '2', '2+', '2-', '10'];
numbers.sort(function (a, b){
var _a = parseFloat(a), // If the values are integers only, parseInt will do too
_b = parseFloat(b);
if (_a - _b === 0) {
return (a > b) ? 1 : -1;
} else {
return _a - _b;
}
});
console.log(numbers);
该函数检查数字值是否相等,如果相等,则回退到字典顺序对字符后缀进行排序。如果相等大小写中没有后缀,则无论返回数字的顺序如何。如果只有一个操作数有后缀,则空数returns为负数。如果数字值不相等,函数简单地 returns 三态,即 a - b
,它将被计算为 negative, 0, positive
之一。或者实际上是 "bistate",因为我们已经处理了 0
个案例。
更通用的解决方案
上面的代码只是两个不同的单字符后缀的特例。如果后缀更复杂,这里有一个更通用的代码来按数字和后缀排序:
var numbers = ['1', '1-r', '1+q', '1', '2', '2+q', '2-r', '10'];
function suffixSort (suff, asc) {
asc = 2 * +(!!asc) - 1; // Convert boolean to -1 or 1
return function (a, b) {
var _a = parseFloat(a), // Extract the number value
_b = parseFloat(b),
aSI = -(a.length - _a.toString().length), // Get the index of suffix start
bSI = -(b.length - _b.toString().length);
// Equal number values, sort by suffixes
if (_a === _b) {
return (suff.indexOf(a.substr(aSI)) > suff.indexOf(b.substr(bSI))) ? 1 : -1;
}
// Inequal number values, sort by numbers
return asc * (_a - _b);
}
}
// suffixSort arguments
// suff: An array of the suffix strings to sort, ordered in the desired sorting order
// asc: true = ascending, false = descending. Optional, defaults to descending sort
numbers.sort(suffixSort(['+q', '-r'], true));
console.log(numbers);
思路是将后缀存储到一个数组中,当需要进行后缀排序时,函数比较后缀的数组索引而不是后缀本身。
suffixSort
还可以让您决定排序方向。选择的排序方向对后缀排序没有影响,它们总是按照它们在 suff
数组中出现的顺序返回。
如果一个数字只有三种可能的状态,并且状态的顺序为 number, number+, number
,则可以通过创建数字的数组表示来重新创建状态,从数组中删除唯一数字,从最小值开始最大,按要求的顺序将空字符串或算术运算符连接到数字,然后将值推送到数组,其中 .toString()
可用于查看数组中已排序值的逗号分隔字符串表示形式
var str = `314+, 1-, 7+, 1, 1-, 271-, 10-
, 10+, 271, 271+, 314-, 314
, 10, 2-, 2, 2+, 7-, 7`;
for (var [nums, order, res, num] = [str.match(/\d+/g), ["", "+", "-"], [], null]
; nums.length
; num = Math.min.apply(Math, nums)
, res = [...res, ...order.map(op => num + op)]
, nums = nums.filter(n => n != num)
);
console.log(res.toString() + "\n", res);
我目前有一组字符串,它们都是数字和带有 + 或 - 的数字。例如:
1 , 1+, 1-, 2, 2+, 2-, 10
当我使用 JavaScript 的排序函数进行排序时,输出:
1、1+、1-、10、2、2+、2-
这是按字典顺序而不是数字顺序。有没有办法对此进行排序,以便数字以正确的方式(第一个列表)出现?我正在使用 ExtJS 商店,因此首选答案作为商店分类器,但普通 javascript 也可以。谢谢?
编辑:这不仅仅是对数字进行排序。
您可以使用 Array#sort
并将元素拆分为数字和其余部分,然后 return 差值或顺序差值。
var array = ['10', '2', '2+', '2-', '1', '1+', '1-'];
array.sort(function (a, b) {
var r = /\d+|\D+/g,
aa = a.match(r),
bb = b.match(r),
order = { '+': 1, '-': 2 };
return aa[0] - bb[0] || (order[aa[1]] || 0) - (order[bb[1]] || 0);
});
console.log(array);
var result=[];
result=array.map(function(n){
if(typeof n==='number') return n;
if(n[n.length-1]=='+'){
return parseInt(n.substring(0,n.length-1))
}
else if(n[n.length-1]=='-'){
return 0-parseInt(n.substring(0,n.length-1))
}
});
result.sort(function(a,b){return a-b})
假设您只想丢弃符号,那么您可以使用 parseInt 和 Array#sort 来获取数字顺序。
var data = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
var sortedData = data.sort(function(a,b){return parseInt(a)-parseInt(b);});
这些值几乎都是整数,因此根据 praseInt
比较它们将 几乎 让你到达那里。唯一缺少的是对具有相同整数部分的值的特殊处理,其中 x-
应该首先出现,然后是 x
,最后是 x+
:
function specialChar(s) {
c = s.substr(-1);
if (c == '+') {
return 1;
}
if (c == '-') {
return -1;
}
return 0;
}
function numCompare(a, b) {
aNum = parseInt(a);
bNum = parseInt(b);
cmp = aNum - bNum;
if (cmp != 0) {
return cmp;
}
// Integer parts are equal - compare the special char at the end
return specialChar(a) - specialChar(b);
}
arr = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
arr.sort(numCompare);
您可以像这样使用自定义排序函数:
var numbers = ['1', '1-', '1+', '2', '2+', '2-', '10'];
numbers.sort(function (a, b){
var _a = parseFloat(a), // If the values are integers only, parseInt will do too
_b = parseFloat(b);
if (_a - _b === 0) {
return (a > b) ? 1 : -1;
} else {
return _a - _b;
}
});
console.log(numbers);
该函数检查数字值是否相等,如果相等,则回退到字典顺序对字符后缀进行排序。如果相等大小写中没有后缀,则无论返回数字的顺序如何。如果只有一个操作数有后缀,则空数returns为负数。如果数字值不相等,函数简单地 returns 三态,即 a - b
,它将被计算为 negative, 0, positive
之一。或者实际上是 "bistate",因为我们已经处理了 0
个案例。
更通用的解决方案
上面的代码只是两个不同的单字符后缀的特例。如果后缀更复杂,这里有一个更通用的代码来按数字和后缀排序:
var numbers = ['1', '1-r', '1+q', '1', '2', '2+q', '2-r', '10'];
function suffixSort (suff, asc) {
asc = 2 * +(!!asc) - 1; // Convert boolean to -1 or 1
return function (a, b) {
var _a = parseFloat(a), // Extract the number value
_b = parseFloat(b),
aSI = -(a.length - _a.toString().length), // Get the index of suffix start
bSI = -(b.length - _b.toString().length);
// Equal number values, sort by suffixes
if (_a === _b) {
return (suff.indexOf(a.substr(aSI)) > suff.indexOf(b.substr(bSI))) ? 1 : -1;
}
// Inequal number values, sort by numbers
return asc * (_a - _b);
}
}
// suffixSort arguments
// suff: An array of the suffix strings to sort, ordered in the desired sorting order
// asc: true = ascending, false = descending. Optional, defaults to descending sort
numbers.sort(suffixSort(['+q', '-r'], true));
console.log(numbers);
思路是将后缀存储到一个数组中,当需要进行后缀排序时,函数比较后缀的数组索引而不是后缀本身。
suffixSort
还可以让您决定排序方向。选择的排序方向对后缀排序没有影响,它们总是按照它们在 suff
数组中出现的顺序返回。
如果一个数字只有三种可能的状态,并且状态的顺序为 number, number+, number
,则可以通过创建数字的数组表示来重新创建状态,从数组中删除唯一数字,从最小值开始最大,按要求的顺序将空字符串或算术运算符连接到数字,然后将值推送到数组,其中 .toString()
可用于查看数组中已排序值的逗号分隔字符串表示形式
var str = `314+, 1-, 7+, 1, 1-, 271-, 10-
, 10+, 271, 271+, 314-, 314
, 10, 2-, 2, 2+, 7-, 7`;
for (var [nums, order, res, num] = [str.match(/\d+/g), ["", "+", "-"], [], null]
; nums.length
; num = Math.min.apply(Math, nums)
, res = [...res, ...order.map(op => num + op)]
, nums = nums.filter(n => n != num)
);
console.log(res.toString() + "\n", res);