简体   繁体   English

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

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

Suppose I have an array假设我有一个数组

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

and I try sorting it, I get something like ...我尝试对其进行排序,我得到类似...

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

notice 10 is before 2, how can I have something more like注意 10 在 2 之前,我怎么能有更多类似的东西

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

Short and sweet, per the original question:根据原始问题,简短而甜蜜:

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"]

(Sort first by type, then by value.) (首先按类型排序,然后按值排序。)


A more-full-featured natural sort:功能更全的自然排序:

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

With naturalSort , pass true as the second parameter if you want "1.13" to sort before "1.2".使用naturalSort ,如果您希望“1.13”在“1.2”之前排序,则将true作为第二个参数传递。

From http://snipplr.com/view/36012/javascript-natural-sort/ by mrhoo:来自 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;
    });
}

Or, from Alphanum: Javascript Natural Sorting Algorithm by Brian Huisman :或者,来自 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("");
}

You could do this in one line using String.prototype.localCompare() and get the result you are looking for.您可以使用String.prototype.localCompare()在一行中完成此操作并获得您正在寻找的结果。 Note that the numeric collation option is enabled.请注意,数字排序选项已启用。

 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"]

Maybe add some logic to handle nulls.也许添加一些逻辑来处理空值。

Please be aware that this will only work with integer numbers .请注意,这只适用于整数 Floating point numbers will not be sorted the way you would hope.浮点数不会按照您希望的方式排序。

// Most natural sorts are for sorting strings, so file2 is sorted before file10 . // 大多数自然排序用于对字符串进行排序,因此file2file10之前排序。

If you are mixing in actual numbers you need to sort them to the front of the array, because negative numbers and digits separated by hyphens are a pain to interpret.如果要混合实际数字,则需要将它们排序到数组的前面,因为负数和用连字符分隔的数字很难解释。 Strings with leading zeroes need to be careful, so part002 will sort before part010 .带前导零的字符串需要小心,因此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)

This is a refined.这是一个精致的。

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

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

If you have only alphabetical and integer items, you can stick with simple code:如果您只有字母和整数项目,您可以坚持使用简单的代码:

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

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

If you can always assume numbers and strings of unmixed alphas, I would just divide and conquer.如果您总是可以假设未混合的 alpha 的数字和字符串,我只会分而治之。 slice out numbers into a new array using typeof.使用 typeof 将数字分割成一个新数组。 Sort both independently and then just join the two arrays.独立排序,然后加入两个数组。

I knew the following way also which might sort the array alphanumerically order.我也知道以下方法可以按字母数字顺序对数组进行排序。

 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