繁体   English   中英

排序数字和字母元素的数组(自然排序)

[英]Sort Array of numeric & alphabetical elements (Natural Sort)

假设我有一个数组

var arr = [1,5,"ahsldk",10,55,3,2,7,8,1,2,75,"abc","huds"];

我尝试对其进行排序,我得到类似...

[1, 1, 10, 2, 2, 3, 5, 55, 7, 75, 8, "abc", "ahsldk", "huds"]

注意 10 在 2 之前,我怎么能有更多类似的东西

[1,1,2,2,3,5 ..., "abc", "ahs...",...]

根据原始问题,简短而甜蜜:

var arr = [1,5,"ahsldk",10,55,3,2,7,8,1,2,75,"abc","huds"];
arr.sort(function(a,b){
  var a1=typeof a, b1=typeof b;
  return a1<b1 ? -1 : a1>b1 ? 1 : a<b ? -1 : a>b ? 1 : 0;
});
// [1, 1, 2, 2, 3, 5, 7, 8, 10, 55, 75, "abc", "ahsldk", "huds"]

(首先按类型排序,然后按值排序。)


功能更全的自然排序:

 var items = ['a1c', 'a01', 'a1', 'a13', 'a1a', 'a1b', 'a3b1', 'a1b0', 'a1b3', 'a1b1', 'dogs', 'cats', 'hogs', 'a2', '2', '20', 1, 13, 1.1, 1.13, '1.2', 'a']; console.log(naturalSort(items)) function naturalSort(ary, fullNumbers) { var re = fullNumbers ? /[\d\.\-]+|\D+/g : /\d+|\D+/g; // Perform a Schwartzian transform, breaking each entry into pieces first for (var i=ary.length;i--;) ary[i] = [ary[i]].concat((ary[i]+"").match(re).map(function(s){ return isNaN(s) ? [s,false,s] : [s*1,true,s]; })); // Perform a cascading sort down the pieces ary.sort(function(a,b){ var al = a.length, bl=b.length, e=al>bl?al:bl; for (var i=1;i<e;++i) { // Sort "a" before "a1" if (i>=al) return -1; else if (i>=bl) return 1; else if (a[i][0]!==b[i][0]) return (a[i][1]&&b[i][1]) ? // Are we comparing numbers? (a[i][0]-b[i][0]) : // Then diff them. (a[i][2]<b[i][2]) ? -1 : 1; // Otherwise, lexicographic sort } return 0; }); // Restore the original values into the array for (var i=ary.length;i--;) ary[i] = ary[i][0]; return ary; }

使用naturalSort ,如果您希望“1.13”在“1.2”之前排序,则将true作为第二个参数传递。

来自 mrhoo 的http://snipplr.com/view/36012/javascript-natural-sort/

Array.prototype.naturalSort= function(){
    var a, b, a1, b1, rx=/(\d+)|(\D+)/g, rd=/\d+/;
    return this.sort(function(as, bs){
        a= String(as).toLowerCase().match(rx);
        b= String(bs).toLowerCase().match(rx);
        while(a.length && b.length){
            a1= a.shift();
            b1= b.shift();
            if(rd.test(a1) || rd.test(b1)){
                if(!rd.test(a1)) return 1;
                if(!rd.test(b1)) return -1;
                if(a1!= b1) return a1-b1;
            }
            else if(a1!= b1) return a1> b1? 1: -1;
        }
        return a.length- b.length;
    });
}

或者,来自 Alphanum: Brian Huisman 的 Javascript 自然排序算法

Array.prototype.alphanumSort = function(caseInsensitive) {
  for (var z = 0, t; t = this[z]; z++) {
    this[z] = [];
    var x = 0, y = -1, n = 0, i, j;

    while (i = (j = t.charAt(x++)).charCodeAt(0)) {
      var m = (i == 46 || (i >=48 && i <= 57));
      if (m !== n) {
        this[z][++y] = "";
        n = m;
      }
      this[z][y] += j;
    }
  }

  this.sort(function(a, b) {
    for (var x = 0, aa, bb; (aa = a[x]) && (bb = b[x]); x++) {
      if (caseInsensitive) {
        aa = aa.toLowerCase();
        bb = bb.toLowerCase();
      }
      if (aa !== bb) {
        var c = Number(aa), d = Number(bb);
        if (c == aa && d == bb) {
          return c - d;
        } else return (aa > bb) ? 1 : -1;
      }
    }
    return a.length - b.length;
  });

  for (var z = 0; z < this.length; z++)
    this[z] = this[z].join("");
}

您可以使用String.prototype.localCompare()在一行中完成此操作并获得您正在寻找的结果。 请注意,数字排序选项已启用。

 var arr = [1,5,"ahsldk",10,55,3,2,7,8,1,2,75,"abc","huds"]; arr.sort((a,b) => ("" + a).localeCompare(b, undefined, {numeric: true})); console.log(arr); // [1, 1, 2, 2, 3, 5, 7, 8, 10, 55, 75, "abc", "ahsldk", "huds"]

也许添加一些逻辑来处理空值。

请注意,这只适用于整数 浮点数不会按照您希望的方式排序。

// 大多数自然排序用于对字符串进行排序,因此file2file10之前排序。

如果要混合实际数字,则需要将它们排序到数组的前面,因为负数和用连字符分隔的数字很难解释。 带前导零的字符串需要小心,因此part002将在part010之前排序。

var natSort=function(as, bs) {
    var a, b, a1, b1,
    rx=  /(\d+)|(\D+)/g, rd= /\d/, rz=/^0/;
    if(typeof as=='number' || typeof bs=='number'){
        if(isNaN(as))return 1;
        if(isNaN(bs))return -1;
        return as-bs;
    }
    a= String(as).toLowerCase();
    b= String(bs).toLowerCase();
    if(a=== b) return 0;
    if(!(rd.test(a) && rd.test(b))) return a> b? 1: -1;
    a= a.match(rx);
    b= b.match(rx);
    while(a.length && b.length){
        a1= a.shift();
        b1= b.shift();
        if(a1!== b1){
            if(rd.test(a1) && rd.test(b1)){
                return a1.replace(rz,'.0')- b1.replace(rz,'.0');
            }
            else return a1> b1? 1: -1;
        }
    }
    return a.length - b.length;
}

array.sort(natSort)

这是一个精致的。

var arr = [1,5,"ahsldk",10,55,3,2,7,8,1,2,75,"56","abc","huds"];
    arr.sort(
                function (a,b){
                    if ( isNaN(a)&&isNaN(b)) return a<b?-1:a==b?0:1;//both are string
                    else if (isNaN(a)) return 1;//only a is a string
                    else if (isNaN(b)) return -1;//only b is a string
                    else return a-b;//both are num
                }
    );

结果:1|1|2|2|3|5|7|8|10|55|56|75|abc|ahsldk|huds|

如果您只有字母和整数项目,您可以坚持使用简单的代码:

var arr = [1,5,"ahsldk",10,55,3,2,7,8,1,2,75,"abc","huds"];
arr.sort(function(a, b)
{
    if (a == b)
        return 0;

    var n1 = parseInt(a, 10);
    var n2 = parseInt(b, 10);
    if (isNaN(n1) && isNaN(n2)) {
        //both alphabetical
        return (a > b) ? 1 : 0;
    }
    else if (!isNaN(n1) && !isNaN(n2)) {
        //both integers
        return (n1 > n2) ? 1 : 0;
    }
    else if (isNaN(n1) && !isNaN(n2)) {
        //a alphabetical and b is integer
        return 1;
    }

    //a integer and b is alphabetical
    return 0;
});

工作示例:http: //jsfiddle.net/25X2e/

如果您总是可以假设未混合的 alpha 的数字和字符串,我只会分而治之。 使用 typeof 将数字分割成一个新数组。 独立排序,然后加入两个数组。

我也知道以下方法可以按字母数字顺序对数组进行排序。

 const arr = [1, 5, "ahsldk", 10, 55, 3, 2, 7, 8, 1, 2, 75, "abc", "huds"]; arr.sort((a, b) => a - b || a.toString().localeCompare(b.toString())); console.log(arr)

var sorted =  ['as', '21sasa0', 'bssll'].sort((a,b) => a.replace(/[0-9]/g,"").localeCompare(b.replace(/[0-9]/g,"")));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM