Trier le tableau des éléments numériques et alphabétiques (Natural Sort)

Supposons que j'ai un tableau

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

Et j'essaie de le trier, j'ai quelque chose comme …

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

L'avis 10 est avant 2, comment puis-je avoir quelque chose de plus comme

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

À partir de http://snipplr.com/view/36012/javascript-natural-sort/ par mrhoo:

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

Ou, de Alphanum: Javascript Natural Sorting Algorithm par Brian Huisman :

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

Court et doux, selon la question originale:

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

(Trier en premier par type, puis par valeur.)


Un type naturel plus complet:

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

// La plupart des sortes naturelles sont pour trier les chaînes,

Alors 'file2' est trié avant 'file10'.

Si vous mélangez en chiffres réels, vous devez les trier à l'avant du tableau,

Car les chiffres et les chiffres négatifs séparés par les traits d'union sont une douleur à interpréter.

Les cordes avec les zéros de pointe doivent être prudentes, alors 'part002' triera avant 'part010'.

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

C'est un raffiné.

 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 ab;//both are num } ); 

Résultat: 1 | 1 | 2 | 2 | 3 | 5 | 7 | 8 | 10 | 55 | 56 | 75 | abc | ahsldk | huds |

Si vous avez uniquement des éléments alphabétiques et entiers, vous pouvez rester avec un code simple:

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

Exemple de travail: http://jsfiddle.net/25X2e/

Si vous pouvez toujours assumer des nombres et des cordes d'alpha non mélangés, je voudrais simplement diviser et conquérir. Tranchez les nombres dans un nouveau tableau en utilisant typeof. Trier les deux indépendamment, puis rejoindre les deux tableaux.