2010-12-07 11 views
9

내가 좋아하는 뭔가를 얻을, 나는정렬 배열 (자연 정렬)

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

과 내가 그것을 정렬하려고 배열이 있다고 가정 ... (10)가 앞에있는

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

통지 2, 어떻게 가질 수있는 일이 더 mrhoo에 의해 http://snipplr.com/view/36012/javascript-natural-sort/에서

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

"자연 정렬"이라는 용어를 찾고 있습니다. – jball

+0

"자바 스크립트 : 자연수 정렬의 영숫자 문자열"참조 http://stackoverflow.com/questions/2802341/natural-sort-of-text-and-numbers-javascript –

답변

13

같은 :

영숫자에서
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; 
    }); 
} 

또는 : Javascript Natural Sorting Algorithm by 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(""); 
} 
+0

2 사이에 차이가 있습니까? 내 첫인식 b4 테스트는 Opera 2 이후로 Opera 2가 더 안정적 일 수 있음을 테스트 한 후 http://jsfiddle.net/sqcFD/에서 오류가 있음을 알았습니다. 1. 아마도 짧은 1이 나를 위해 일할 것입니다. –

+0

@jiewmeng 필자는 첫 번째 테스트 만했다. 두 번째 테스트는 견고하다는 결론을 내렸다. (분석의 깊이와 코드를 바탕으로) 두 번째 테스트는 단단했다. – jball

+0

참고'Array.prototype.alphanumSort'는 입력 배열에 문자열 만 필요합니다. – gradbot

1

당신은 항상 숫자와 혼합되지 않은 알파의 문자열을 가정 할 수 있다면, 난 그냥 분할 및 정복 할 것입니다. typeof를 사용하여 숫자를 새로운 배열로 분할하십시오. 둘 다 독립적으로 정렬 한 다음 두 배열을 조인하십시오.

2

만 알파벳이 정수 항목, 당신은 간단한 코드를 고수 할 수있는 경우 :

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/

+0

'단순한'것으로 분류 할 수 있을지 모르겠다. :) – Phrogz

13

원래의 질문에 따라, 짧은 달콤한 :

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

(유형별로 정렬 한 다음 값순으로 정렬)


더-완전한 기능을 갖춘 자연 종류 : 당신이 "1.2"전에 정렬 "1.13"를 원하는 경우 naturalSort

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

가, 두 번째 매개 변수로 true를 전달합니다.

+1

숫자가있는 경우 문자열''55 "'잘못 정렬했다. http://jsfiddle.net/8VjWL/, 일반적으로 작동한다. –

+2

@jiewmeng 이것은 질문의 일부가 아니었다. 또한 문자열에 숫자가있는 경우 ... 숫자가 아닌 문자열이 있으므로 배열을보다 정확하게 채워야합니다. : p (실제로 원한다면'* 1' 또는'parseFloat'를 첫 번째 정렬 기준으로 추가 할 수 있습니다. 그러나 실제로는 numbers-as-strings로 배열을 받아 들여야 만 가능합니다) – Phrogz

+0

+1 숫자가 문자열로 위장되지 않는 더 깨끗한 경우를위한 명확한 코드. – jball

6

// 대부분의 자연 종류의

그래서 '파일 2'는 'file10'전에 정렬, 정렬 문자열입니다.

당신이 배열의 전면을 정렬 할 필요가 실제 숫자를 혼합하는 경우

,

음수와 하이픈으로 구분 된 숫자는 해석 고통 때문이다.

'0'이있는 문자열은주의해야하므로 'part002'는 '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)는

+1

jball의 첫 번째 예와 비슷하게 보입니다. 왜냐하면 나는 일명 mrhoo이기 때문입니다. – kennebec

+0

이 작업은 가능하지만 정규 표현식을 사용하기 때문에 거대한 배열의 경우 속도가 느릴 수 있습니다./ – Jaro

5

이 정제된다.

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 | HUD의 |

+0

Chrome의 빠른 프로필 세션에서이 답변이 가장 빠릅니다. Phrogz 솔루션보다 약간 빠르고 jball의 솔루션보다 더 빠릅니다. – gradbot

+1

나는 임시 변수를 사용하여 10 %의 속도 증가를 측정했습니다. var as = isNaN (a), bs = isNaN (b); ' – gradbot

+0

쉽게 정규 표현식이 처리되는 것을 볼 수 있습니다. 어쩌면 그 중 하나의 유형일까요? – pinichi