如何对一组数字进行字典序和数值上的排序?

4
我目前有一组字符串,其中既有数字也有带有+或-符号的数字,例如:

1, 1+, 1-, 2, 2+, 2-, 10

使用JavaScript的排序函数进行排序后得到:

1, 1+, 1-, 10, 2, 2+, 2-

这是按字典顺序排序而不是按数值大小排序。有没有一种方法可以使数字按正确的方式(第一个列表)排序?我正在使用ExtJS存储器,因此首选作为存储器排序器的答案,但纯JavaScript也可以。谢谢。

编辑:这不仅仅是对数字进行排序。


1
1+1-等不是数字,如何对非数字的东西进行数值排序? - Teemu
1
@NinaScholz No. 1和符号- - oneCoderToRuleThemAll
2
这不仅仅是对数字进行排序。还有什么? - Nina Scholz
@Teemu 仍然不明白。如果列表已经是“如下所示:1,1+,1-,2,2+,2-,10”,并且这是“正确的方式(第一个列表)”,为什么还需要“排序”呢? - guest271314
1
@guest271314 这是OP第一个例子中的顺序。这也是我的答案中的顺序。这是一个“数字顺序”,但OP也为符号定义了顺序。如果我没有误解问题,那么顺序应该是number,number +,number-。当OP说第一个列表的顺序是正确的时候,排序函数不应该返回相同的顺序,尽管原始数组已经处于正确的顺序吗? - Teemu
显示剩余6条评论
6个回答

3
您可以如下使用自定义排序函数:

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);

该函数检查数字值是否相等,如果相等,则退回到词典排序以对字符后缀进行排序。如果在相等情况下没有后缀,则无论以哪种顺序返回数字都没有关系。如果只有一个操作数具有后缀,则裸数返回负数。如果数字值不相等,则该函数简单地返回三态,即a-b,它将被评估为negative, 0, positive之一。实际上,这是一个“双态”,因为我们已经处理了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 数组中出现的顺序返回。


0
你可以使用 Array#sort,将元素拆分为数字和其他部分,然后返回差异或顺序的差异。

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);


0
如果一个数字只有三种可能的状态,并且这些状态的顺序是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);


0
  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})

希望你的IP是数组=[1,'1+ ','1-',2,'2+','2-',10]; - nivendha

0

这些值几乎是整数,因此根据 parseInt 进行比较将会 几乎 让您成功。唯一缺少的是对于具有相同整数部分的值进行特殊处理,在这种情况下应该首先加上 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);

如果(cmp!= 0){返回cmp;} 这样处理“3-”和“2+”不正确吗? - serg
@serg 你为什么这样认为呢?就我理解OP的需求来说,2+(读作:两加)应该在3-(读作:三减,而不是负三)之前。 - Mureinik
啊,如果是三减去某数的话那就对了,我以为是负三呢,不知道为什么这么想。 - serg

-1
假设你只想抛弃符号,那么你可以使用 parseInt 和 Array#sort 来按数字顺序排序。
var data = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
var sortedData = data.sort(function(a,b){return parseInt(a)-parseInt(b);});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接