
Home Contact Binary Search Sort Multiple Columns Filing Functions Extracting Excel data Read and Write .csv files Show Progress Messages Send Automatic Email Running under .hta Setting Folder Attributes Long-script warnings Desktop Shortcut
| SORT SINGLE- & MULTI-DIMENSIONAL ARRAYS Javascript has an efficient built-in algorithm in its sort() function. However, this only sorts lexographically. Therefore, an additional, purpose-built function is required to handle particular data types, The SortIt() function uses the Javascript sort() function to sort single- or multiple-dimensioned arrays (columns) in numerical/alphnumerical order, with numerals first. An alphanumical example would be, say, 'TY6VB98'. This type of data is sorted lexographically. In a recent application, arrays involving up to 10 columns of data and 250kB of data had to be sorted. In this case, the greatest required depth turned out to be a sort on 6 columns. SortIt() does this pretty quickly. /* This example of SortIt is set up for six columns of multi-dimensional array, in column order of u,v,w,x,y,z (column numbers). Edit the code to reduce or increase the maximum columns allowed, to suit your use. Note that the sort will only continue as far as the specified number of columns in the call, ie, "w,x" only sorts on two columns, etc. SortIt will place numbers before strings, and swap until all columns are in ascending order, with precedence specified by the column order of the call. To get sort in descending order, use the standard function: TheArr.reverse(), after the sort. One can shorten or lengthen the function according to the number of columns that it is desired to sort. One could also use recursion to do the multiple ops, or use an internal function. I left it this way for clarity, to avoid setting variables, for speed, and because my application's javascript involved some 5000 lines of code, anyway. FOR EXAMPLE, BEFORE SORT (The example indicates a four-column sort) An array of [Bay , Style , Size , Quantity] arrays as in : myArr[0][BB-87,31256,5,78]; myArr[1][AE-76,1-11123,2h,45]; etc.....: 3RD Fl,2351,12,456 DA-65,4521,4h,45 UY-32,1-785,7,210 3RD Fl,2351,5,85 ZZ-65,M4548,6h,21 3RD Fl,2351,12,21 SortIt(Arr,1,2,3,0); <----Columns: sort on Style, Size, Quantity, Bay Arr out = 3RD Fl,2351,5,85 3RD Fl,2351,12,21 3RD Fl,2351,12,456 DA-65,4521,4h,45 BB-87,31256,5,78 AE-76,1-11123,2h,45 UY-32,1-785,7,210 ZZ-65,M4548,6h,21 Then, for comparison: sort on Bay, etc SortIt(Arr,0,1,2,3); Arr out = 3RD Fl,2351,5,85 3RD Fl,2351,12,21 3RD Fl,2351,12,456 AE-76,1-11123,2h,45 BB-87,31256,5,78 DA-65,4521,4h,45 UY-32,1-785,7,210 ZZ-65,M4548,6h,21 */ // GENERAL SORT FUNCTION: // Sort on single or multi-column arrays. // Sort set up for six colums, in order of u,v,w,x,y,z. For single columns (single-dimensioned array), omit all u,v.... // Sort will continue only as far as the specified number of columns: "w,x" only sorts on two columns, etc. // Sort will place numbers before strings, and swap until all columns are in ascending order. // Sorter algorithm: // Is result of a-b NaN?. Then one or both is text. // Are both text? Then do a general swap. Set var 'swap' to 1:0:-1, accordingly: 1 push up list, -1 push down. // Else one is text, the other a number. Therefore, is 'a' text? Then push up, else 'b' is text - push 'a' down. // Else both are numbers. // return result in var 'swap'. // To do multi-columns, repeat the operations for each column. // To do ascending.descending, asending, etc columns, see the code further down the page. function SortIt(TheArr,u,v,w,x,y,z){ if(u==undefined){TheArr.sort(Sortsingle);} // this is a simple array, not multi-dimensional, ie, SortIt(TheArr); else{TheArr.sort(Sortmulti);} function Sortsingle(a,b){ var swap=0; if(isNaN(a-b)){ if((isNaN(a))&&(isNaN(b))){swap=(b<a)-(a<b);} else {swap=(isNaN(a)?1:-1);} } else {swap=(a-b);} return swap; } function Sortmulti(a,b){ var swap=0; if(isNaN(a[u]-b[u])){ if((isNaN(a[u]))&&(isNaN(b[u]))){swap=(b[u]<a[u])-(a[u]<b[u]);} else{swap=(isNaN(a[u])?1:-1);} } else{swap=(a[u]-b[u]);} if((v==undefined)||(swap!=0)){return swap;} else{ if(isNaN(a[v]-b[v])){ if((isNaN(a[v]))&&(isNaN(b[v]))){swap=(b[v]<a[v])-(a[v]<b[v]);} else{swap=(isNaN(a[v])?1:-1);} } else{swap=(a[v]-b[v]);} if((w==undefined)||(swap!=0)){return swap;} else{ if(isNaN(a[w]-b[w])){ if((isNaN(a[w]))&&(isNaN(b[w]))){swap=(b[w]<a[w])-(a[w]<b[w]);} else{swap=(isNaN(a[w])?1:-1);} } else{swap=(a[w]-b[w]);} if((x==undefined)||(swap!=0)){return swap;} else{ if(isNaN(a[x]-b[x])){ if((isNaN(a[x]))&&(isNaN(b[x]))){swap=(b[x]<a[x])-(a[x]<b[x]);} else{swap=(isNaN(a[x])?1:-1);} } else{swap=(a[x]-b[x]);} if((y==undefined)||(swap!=0)){return swap;} else{ if(isNaN(a[y]-b[y])){ if((isNaN(a[y]))&&(isNaN(b[y]))){swap=(b[y]<a[y])-(a[y]<b[y]);} else{swap=(isNaN(a[y])?1:-1);} } else{swap=(a[y]-b[y]);} if((z=undefined)||(swap!=0)){return swap;} else{ if(isNaN(a[z]-b[z])){ if((isNaN(a[z]))&&(isNaN(b[z]))){swap=(b[z]<a[z])-(a[z]<b[z]);} else{swap=(isNaN(a[z])?1:-1);} } else{swap=(a[z]-b[z]);} return swap; } } } } } } } // Recently (20 Dec 2008), I received a query regarding mixed ascending/descending sort order (say col'm 0 ascending, // col'm 1, descending, other columns also mixed...). The following code handles this requirement. // Note: If you then wish to do a binary search on a reverse-sorted column, you'd have to reverse the array prior to // using BinSearch(). function SortIt(TheArr,us,u,vs,v,ws,w,xs,x,ys,y,zs,z){ // us-zs: 1=asc, -1=desc. u-z: column-numbers. See example if(u==undefined){TheArr.sort(Sortsingle);} // if this is a simple array, not multi-dimensional, ie, SortIt(TheArr,1): ascending. else{TheArr.sort(Sortmulti);} function Sortsingle(a,b){ var swap=0; if(isNaN(a-b)){ if((isNaN(a))&&(isNaN(b))){swap=(b<a)-(a<b);} else {swap=(isNaN(a)?1:-1);} } else {swap=(a-b);} return swap*us; } function Sortmulti(a,b){ var swap=0; if(isNaN(a[u]-b[u])){ if((isNaN(a[u]))&&(isNaN(b[u]))){swap=(b[u]<a[u])-(a[u]<b[u]);} else{swap=(isNaN(a[u])?1:-1);} } else{swap=(a[u]-b[u]);} if((v==undefined)||(swap!=0)){return swap*us;} else{ if(isNaN(a[v]-b[v])){ if((isNaN(a[v]))&&(isNaN(b[v]))){swap=(b[v]<a[v])-(a[v]<b[v]);} else{swap=(isNaN(a[v])?1:-1);} } else{swap=(a[v]-b[v]);} if((w==undefined)||(swap!=0)){return swap*vs;} else{ if(isNaN(a[w]-b[w])){ if((isNaN(a[w]))&&(isNaN(b[w]))){swap=(b[w]<a[w])-(a[w]<b[w]);} else{swap=(isNaN(a[w])?1:-1);} } else{swap=(a[w]-b[w]);} if((x==undefined)||(swap!=0)){return swap*ws;} else{ if(isNaN(a[x]-b[x])){ if((isNaN(a[x]))&&(isNaN(b[x]))){swap=(b[x]<a[x])-(a[x]<b[x]);} else{swap=(isNaN(a[x])?1:-1);} } else{swap=(a[x]-b[x]);} if((y==undefined)||(swap!=0)){return swap*xs;} else{ if(isNaN(a[y]-b[y])){ if((isNaN(a[y]))&&(isNaN(b[y]))){swap=(b[y]<a[y])-(a[y]<b[y]);} else{swap=(isNaN(a[y])?1:-1);} } else{swap=(a[y]-b[y]);} if((z=undefined)||(swap!=0)){return swap*ys;} else{ if(isNaN(a[z]-b[z])){ if((isNaN(a[z]))&&(isNaN(b[z]))){swap=(b[z]<a[z])-(a[z]<b[z]);} else{swap=(isNaN(a[z])?1:-1);} } else{swap=(a[z]-b[z]);} return swap*zs; } } } } } } } To test the ascending/descending code, I used the following: TestArr=new Array([2,8,1,'BAS',5,9],[5,1,2,'DES',1,5],[5,9,1,'GOL',8,3],[8,2,2,'NUY',4,7],[5,7,2,'VIC',2,2],[6,7,8,'ABL',4,1], [5,9,1,'KHF',8,3],[8,2,0,'MOYT',8,1],[5,0,3,'AVGR',7,2],[5,8,2,'MU89',7,5]); // This array needs many more elements to illustrate the function well. Preferably use real data... document.write('<BR>Un-Sorted:<BR><BR>'); for(var i=0;i<10;i++){document.write(TestArr[i]+'<BR>');} SortIt(TestArr,1,0,-1,1,1,2,-1,3);; document.write('<BR>Sorted: 4 col in order: 0,1,2,3 in order: asc, desc, asc, des<BR><BR>'); for(var i=0;i<10;i++){document.write(TestArr[i]+'<BR>');}
SortIt(TestArr,1,2,-1,1,-1,3,1,0,-1,5,1,4); document.write('<BR>Sorted: 6 col in order: 2,1,3,0,5,4 in order: asc, desc, desc, asc, desc, asc<BR><BR>'); for(var i=0;i<10;i++){document.write(TestArr[i]+'<BR>');}
Top
| |