2010-12-07 26 views
9

मान लीजिए मैं एक सरणीक्रमबद्ध सरणी (प्राकृतिक क्रमबद्ध)

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...",...] 
+2

आप "प्राकृतिक प्रकार" शब्द की तलाश में हैं। – jball

+0

http://stackoverflow.com/questions/2802341/natural-sort-of-text-and-numbers-javascript –

उत्तर

13
mrhoo द्वारा

http://snipplr.com/view/36012/javascript-natural-sort/ से की तरह:

0,123,
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 से: 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 के बीच कोई अंतर है? मेरा पहला इंप्रेशन बी 4 उनका परीक्षण कर रहा था, शायद दूसरा (ओपेरा) 1 अधिक विश्वसनीय होगा, क्योंकि ओपेरा से, हालांकि परीक्षण के बाद, http://jsfiddle.net/sqcFD/, मुझे पता चला कि मुझे एक त्रुटि मिली है वह 1. शायद छोटा 1 मेरे लिए काम करेगा। –

+0

@jiewmeng मैंने केवल पहले परीक्षण किया - मैंने माना (विश्लेषण की गहराई और कोड पर एक त्वरित नज़र के आधार पर) कि दूसरा ठोस था ... अगर यह आपके लिए काम कर रहा है तो पहले व्यक्ति के साथ चिपके रहें। – jball

+0

नोट 'Array.prototype.alphanumSort' के लिए आवश्यक है कि इनपुट सरणी में केवल स्ट्रिंग हों। – gradbot

1

आप हमेशा नंबर और अमिश्रित alphas के तार मान सकते हैं, तो मैं सिर्फ विभाजित और जीत होगी। टाइपफ का उपयोग कर एक नई सरणी में संख्याओं को टुकड़ा करें। दोनों स्वतंत्र रूप से क्रमबद्ध करें और फिर केवल दो सरणी में शामिल हों।

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

(टाइप करके पहले क्रमबद्ध करें, फिर मूल्य के अनुसार।)


एक और अधिक-पूर्ण विशेषताओं प्राकृतिक प्रकार:

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 के साथ, दूसरा पैरामीटर के रूप में true पारित यदि आप "1.2" से पहले क्रमबद्ध करना चाहते हैं "1.13"।

+1

यदि मेरे पास कोई संख्या है एक स्ट्रिंग '55" 'यह गलत तरीके से टाइप की जाती है, http://jsfiddle.net/8VjWL/, यह आमतौर पर –

+2

@jiewmeng काम करता है यह आपके प्रश्न का हिस्सा नहीं था। इसके अलावा, यदि आपके पास स्ट्रिंग में कोई संख्या है ... तो आपके पास एक स्ट्रिंग है और कोई संख्या नहीं है, और आपको अपनी सरणी को अधिक सटीक रूप से पॉप्युलेट करना चाहिए। : पी (यदि आप वास्तव में चाहते थे तो आप अपने पहले प्रकार के मानदंड के रूप में '* 1' या 'parseFloat' जोड़ सकते हैं, लेकिन मैं आपको केवल यह करने के लिए प्रोत्साहित करता हूं अगर आपको वास्तव में संख्याओं के साथ सरणी स्वीकार करनी होंगी।) – Phrogz

+0

+1 क्लीनर मामलों के लिए निश्चित रूप से सरल कोड जहां कोई संख्या तारों के रूप में मजाक कर रही है। – jball

6

// अधिकांश प्राकृतिक प्रकार छँटाई स्ट्रिंग्स के लिए कर रहे हैं,

तो 'करें 2' 'file10' से पहले सॉर्ट की गई है।

आप वास्तविक संख्या आप सरणी के सामने करने के लिए उन्हें सुलझाने के लिए की जरूरत है मिश्रण रहे हैं, तो

क्योंकि ऋणात्मक संख्याओं और हाइफ़न से अलग कर दिया अंक व्याख्या करने के लिए एक दर्द कर रहे हैं।

अग्रणी शून्यों के साथ स्ट्रिंग सावधान रहना आवश्यक है, इसलिए '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

यह जब्बल के पहले उदाहरण के समान दिखता है, क्योंकि मैं उर्फ ​​मिहू हूं। – 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 | एबीसी | ahsldk | HUDs |

+0

क्रोम में एक त्वरित प्रोफ़ाइल सत्र इस उत्तर को सबसे तेज़ दिखाता है। यह फोर्ज़ समाधान से थोड़ा तेज़ है और जब्बल के समाधानों की तुलना में तेज़ी से तीव्रता है। – gradbot

+1

मैंने temp vars 'var के रूप में = isNaN (ए), बीएस = isNaN (बी) का उपयोग करके 10% की गति वृद्धि को माप लिया; ' – gradbot

+0

आसान देखें कि रेगेक्स प्रसंस्करण निगलता है। शायद या तो टाइप? – pinichi

संबंधित मुद्दे