Skip to content

Commit 6659a68

Browse files
committed
Merge pull request #23 from tablesort/master
Fix javascript error
2 parents f31de6a + 396f774 commit 6659a68

3 files changed

Lines changed: 610 additions & 524 deletions

File tree

naturalSort.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ function naturalSort (a, b) {
3333
}
3434
// natural sorting through split numeric strings and default strings
3535
for(var cLoc=0, xNl = xN.length, yNl = yN.length, numS=Math.max(xNl, yNl); cLoc < numS; cLoc++) {
36-
oFxNcL = normChunk(xN[cLoc], xNl);
37-
oFyNcL = normChunk(yN[cLoc], yNl);
36+
oFxNcL = normChunk(xN[cLoc] || '', xNl);
37+
oFyNcL = normChunk(yN[cLoc] || '', yNl);
3838
// handle numeric vs string comparison - number < string - (Kyle Adams)
3939
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; }
4040
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'

speed-tests.html

Lines changed: 151 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,104 +2,178 @@
22
<html>
33
<head>
44
<script src="naturalSort.js" type="text/javascript"></script>
5-
5+
<style>
6+
* { font-family: tahoma; }
7+
textarea{ width: 200px; }
8+
.true { color: green; }
9+
.false { color: red; }
10+
</style>
11+
</head>
12+
<body style="display:none;"></body>
613
<script>
14+
/*
15+
* Alphanum
16+
* http://my.opera.com/GreyWyvern/blog/show.dml/1671288
17+
*/
18+
function alphanum(a, b) {
19+
function chunkify(t) {
20+
var tz = [], x = 0, y = -1, n = 0, i, j;
21+
22+
while (i = (j = t.charAt(x++)).charCodeAt(0)) {
23+
var m = (i == 46 || (i >=48 && i <= 57));
24+
if (m !== n) {
25+
tz[++y] = "";
26+
n = m;
27+
}
28+
tz[y] += j;
29+
}
30+
return tz;
31+
}
32+
33+
var aa = chunkify(a);
34+
var bb = chunkify(b);
35+
36+
for (x = 0; aa[x] && bb[x]; x++) {
37+
if (aa[x] !== bb[x]) {
38+
var c = Number(aa[x]), d = Number(bb[x]);
39+
if (c == aa[x] && d == bb[x]) {
40+
return c - d;
41+
} else return (aa[x] > bb[x]) ? 1 : -1;
42+
}
43+
}
44+
return aa.length - bb.length;
45+
}
746

847
/* Mike Grier's fixes on v0.2 http://mgrier.com/code/natsort.optimized.txt */
948
function naturalSort2(a,b){
10-
// setup temp-scope variables for comparison evauluation
11-
var x = a.toString().toLowerCase() || '',
12-
re=/(-?[0-9.]+)/g,
13-
y = b.toString().toLowerCase() || '',
14-
nC = String.fromCharCode(0),
15-
xN = x.replace( re, nC + '$1' + nC ).split(nC),
16-
yN = y.replace( re, nC + '$1' + nC ).split(nC),
17-
xD = (new Date(x)).getTime(),yD;
18-
19-
if(xD) yD = (new Date(y)).getTime(); //no point in getting yD if xD is not a date
20-
21-
// natural sorting of dates
22-
if(yD){ // we already checked if(xD), so if(yD), it's a date, too
23-
if( xD < yD ) return -1;
24-
else if( xD > yD ) return 1;
25-
}
26-
27-
// natural sorting through split numeric strings and default strings
28-
var cLoc, numS=Math.max(xN.length,yN.length);
29-
for(cLoc=0; cLoc<numS; cLoc++){
30-
// instead of performing these next 6 operations in the if
31-
// and the same 6 operations in the else if, just do them once
32-
// so we can reuse results instead of computing twice
33-
xNcL = xN[cLoc]; // only look up values
34-
yNcL = yN[cLoc]; // in arrays once
35-
FxNcL = parseFloat(xNcL);
36-
FyNcL = parseFloat(yNcL);
37-
oFxNcL = FxNcL || xNcL;
38-
oFyNcL = FyNcL || yNcL;
39-
40-
if(oFxNcL < oFyNcL)return -1;
41-
else if(oFxNcL > oFyNcL)return 1;
42-
}
43-
return 0;
49+
// setup temp-scope variables for comparison evauluation
50+
var x = a.toString().toLowerCase() || '',
51+
re=/(-?[0-9.]+)/g,
52+
y = b.toString().toLowerCase() || '',
53+
nC = String.fromCharCode(0),
54+
xN = x.replace( re, nC + '$1' + nC ).split(nC),
55+
yN = y.replace( re, nC + '$1' + nC ).split(nC),
56+
xD = (new Date(x)).getTime(),yD;
57+
58+
if(xD) yD = (new Date(y)).getTime(); //no point in getting yD if xD is not a date
59+
60+
// natural sorting of dates
61+
if(yD){ // we already checked if(xD), so if(yD), it's a date, too
62+
if( xD < yD ) return -1;
63+
else if( xD > yD ) return 1;
64+
}
65+
66+
// natural sorting through split numeric strings and default strings
67+
var cLoc, numS=Math.max(xN.length,yN.length);
68+
for(cLoc=0; cLoc<numS; cLoc++){
69+
// instead of performing these next 6 operations in the if
70+
// and the same 6 operations in the else if, just do them once
71+
// so we can reuse results instead of computing twice
72+
xNcL = xN[cLoc]; // only look up values
73+
yNcL = yN[cLoc]; // in arrays once
74+
FxNcL = parseFloat(xNcL);
75+
FyNcL = parseFloat(yNcL);
76+
oFxNcL = FxNcL || xNcL;
77+
oFyNcL = FyNcL || yNcL;
78+
79+
if(oFxNcL < oFyNcL)return -1;
80+
else if(oFxNcL > oFyNcL)return 1;
81+
}
82+
return 0;
4483
}
4584

4685
/*
4786
* Natural Sort algorithm for Javascript
48-
* Version 0.3
87+
* Version 0.3
4988
* Author: Jim Palmer (based on chunking idea from Dave Koelle)
50-
* optimizations and safari fix by Mike Grier (mgrier.com)
89+
* optimizations and safari fix by Mike Grier (mgrier.com)
5190
* Released under MIT license.
5291
*/
5392
function naturalSort3(a, b){
54-
// setup temp-scope variables for comparison evauluation
55-
var re = /(-?[0-9\.]+)/g,
56-
x = a.toString().toLowerCase() || '',
57-
y = b.toString().toLowerCase() || '',
58-
nC = String.fromCharCode(0),
59-
xN = x.replace( re, nC + '$1' + nC ).split(nC),
60-
yN = y.replace( re, nC + '$1' + nC ).split(nC),
61-
xD = (new Date(x)).getTime(),
62-
yD = xD ? (new Date(y)).getTime() : null;
63-
// natural sorting of dates
64-
if ( yD )
65-
if ( xD < yD ) return -1;
66-
else if ( xD > yD ) return 1;
67-
// natural sorting through split numeric strings and default strings
68-
for( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) {
69-
oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];
70-
oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];
71-
if (oFxNcL < oFyNcL) return -1;
72-
else if (oFxNcL > oFyNcL) return 1;
73-
}
74-
return 0;
93+
// setup temp-scope variables for comparison evauluation
94+
var re = /(-?[0-9\.]+)/g,
95+
x = a.toString().toLowerCase() || '',
96+
y = b.toString().toLowerCase() || '',
97+
nC = String.fromCharCode(0),
98+
xN = x.replace( re, nC + '$1' + nC ).split(nC),
99+
yN = y.replace( re, nC + '$1' + nC ).split(nC),
100+
xD = (new Date(x)).getTime(),
101+
yD = xD ? (new Date(y)).getTime() : null;
102+
// natural sorting of dates
103+
if ( yD )
104+
if ( xD < yD ) return -1;
105+
else if ( xD > yD ) return 1;
106+
// natural sorting through split numeric strings and default strings
107+
for( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) {
108+
oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];
109+
oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];
110+
if (oFxNcL < oFyNcL) return -1;
111+
else if (oFxNcL > oFyNcL) return 1;
112+
}
113+
return 0;
75114
}
76115

77-
var a = [], b = [], c = [];
116+
var t, diff, a = [], b = [], c = [], d = [];
78117
for ( var i = 0; i < 1000; i++ ) {
79-
a.push(String.fromCharCode( Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65 ));
80-
b.push(String.fromCharCode( Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65 ));
81-
c.push(String.fromCharCode( Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65 ));
118+
t = String.fromCharCode( Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65, Math.floor(Math.random() * (90-66)) + 65 );
119+
a.push(t);
120+
b.push(t);
121+
c.push(t);
122+
d.push(t);
82123
}
83124
for ( i = 0; i < 1000; i++ ) {
84-
a.push(Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString() );
85-
b.push(Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString() );
86-
c.push(Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString() );
125+
t = Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString() + Math.floor(Math.random() * 9).toString();
126+
a.push(t);
127+
b.push(t);
128+
c.push(t);
129+
d.push(t);
87130
}
88131
for ( i = 0; i < 1000; i++ ) {
89-
a.push( (Math.floor(Math.random() * 12) + 1).toString() + '/' + (Math.floor(Math.random() * 28) + 1).toString() + '/' + ( 2009 - Math.floor(Math.random() * 2)) );
90-
b.push( (Math.floor(Math.random() * 12) + 1).toString() + '/' + (Math.floor(Math.random() * 28) + 1).toString() + '/' + ( 2009 - Math.floor(Math.random() * 2)) );
91-
c.push( (Math.floor(Math.random() * 12) + 1).toString() + '/' + (Math.floor(Math.random() * 28) + 1).toString() + '/' + ( 2009 - Math.floor(Math.random() * 2)) );
132+
t = (Math.floor(Math.random() * 12) + 1).toString() + '/' + (Math.floor(Math.random() * 28) + 1).toString() + '/' + ( 2009 - Math.floor(Math.random() * 2));
133+
a.push(t);
134+
b.push(t);
135+
c.push(t);
136+
d.push(t);
92137
}
93138

94-
var d = new Date();
95-
document.write(a.sort(naturalSort)[0] + ' <BR>[' + ((new Date()).getTime() - d.getTime()) + 'ms]<BR><BR>');
96-
//d = new Date();
97-
//document.write(b.sort(naturalSort2)[0] + ' <BR>[' + ((new Date()).getTime() - d.getTime()) + 'ms]<BR><BR>');
98-
//d = new Date();
99-
//document.write(c.sort(naturalSort3)[0] + ' <BR>[' + ((new Date()).getTime() - d.getTime()) + 'ms]');
139+
function dateStr( diff ) {
140+
return ', Time = [' + ((new Date()).getTime() - diff.getTime()) + 'ms]';
141+
};
142+
143+
function matchingResults( str, z, suffix ) {
144+
var i, diff = a.join(' ') === z.join(' ');
145+
str += '<br>matches naturalSort result: <span class="' + diff + '">' + diff + '</span><br>';
146+
if (!diff) {
147+
str += '<textarea>Showing first 500 elements:\n';
148+
// only show first 500 elements
149+
for ( i = 0; i < 500; i++ ) {
150+
str += a[i] + ( a[i] === z[i] ? ' = ' : ' \u2260 ' ) + z[i] + '\n';
151+
}
152+
str += '</textarea>';
153+
}
154+
document.write( str + ( suffix || '' ) );
155+
};
156+
157+
diff = new Date();
158+
document.write(
159+
'<h1>Speed Tests</h1>All natural sorting algorithms are using the same data set' +
160+
'<h2>naturalSort</h2>first element = ' + a.sort(naturalSort)[0] + dateStr( diff )
161+
);
162+
163+
diff = new Date();
164+
matchingResults(
165+
'<h2>alphanum</h2>first element = ' + b.sort(alphanum)[0] + dateStr( diff ),
166+
b,
167+
'<br>*Note: alphanum does not sort dates'
168+
);
169+
170+
diff = new Date();
171+
matchingResults( '<h2>naturalSort2</h2>first element = ' + c.sort(naturalSort2)[0] + dateStr( diff ), c );
172+
173+
diff = new Date();
174+
matchingResults( '<h2>naturalSort3</h2>first element = ' + d.sort(naturalSort3)[0] + dateStr( diff ), d );
175+
176+
document.getElementsByTagName('body')[0].style.display = '';
100177

101178
</script>
102-
<style>*{font-family:tahoma;font-size:9px;}</style>
103-
</head>
104-
<body></body>
105179
</html>

0 commit comments

Comments
 (0)