PDA

View Full Version : Sorting mixed values

mhodgson
07-02-2008, 12:05 PM
Hi,
Is there a way to sort mixed values (e.g. 2a, 2c, 2b, 3c, 1c, 5a).
I need to sort them by number then by letter (e.g 1c, 2a,2b,2c,3c,5a). There are only w letters, a,b,c and w on its own(no number in front).

The sorting script I have will only sort by integers or by strings.

example of part of the script- Maybe I need to change the letters to a numeric value? so w becomes 0, 2a becomes 21 and 2b becomes 22 and 3c becomes 31 and then allowing this bit to sort it.

Any suggestions?

// If the item matches a numeric pattern
if (itm.match(/(\d*,\d*\$)|(^-?\d\d*\.\d*\$)|(^-?\d\d*\$)|(^-?\.\d\d*\$)/)) {
// Replace anything that is not part of a number (decimal pt, neg sign, or 0 through 9) with an empty string.
sortValue = itm.replace(/[^0-9.-]/g,'');
// sortValue = sortValue.replace(/,/g,'');
if (isNaN(sortValue)) {
sortValue = 0;
} else {
sortValue = parseFloat(sortValue);
}
}

jscheuer1
07-02-2008, 03:02 PM
I came up with this demo, I put letters only at the end, but they could go at the beginning (just get rid of the highlighted lines):

<script type="text/javascript">
Array.prototype.numlet = function(){
var t = [], r = [], o = {};
var n = function(item){return isNaN(parseInt(item))? 0 : parseInt(item);};
var c = function(item){return typeof item == 'string' && item.length==2? n(item.charAt(0)) : 0;};
for (var i = this.length - 1; i > -1; --i)
if(!o[c(this[i])])
o[c(this[i])] = [this[i]];
else o[c(this[i])][o[c(this[i])].length] = this[i];
for (var p in o){
t[t.length] = p;
o[p].sort();
}
t.sort();
for(var i = 0; i < t.length; ++i)
if(t[i] - 0)
r = r.concat(o[t[i]]);
if(t[0] == 0)
r = r.concat(o[0]);
for (var i = this.length - 1; i > -1; --i)
this[i] = r[i];
}
var x = ['2c','b','4z','3y','w','3c','4t','2a','9a', '3q'];
x.numlet();
</script>

The code is a little more complex than it has to be, as long as the items in your array to be sorted like this are in the exact format you describe. If for example one of them were to be a raw number, it would be treated as a single letter. It can get a little confusing, because 2c ,3a, etc. are technically numbers in certain cases (hex), but '2c', and '3a' are strings.

Also, the code could possibly be simplified, even while retaining this primitive error checking.

jscheuer1
07-02-2008, 05:40 PM
Yeah, I was right, here is a bit simpler method (requires IE 5.5 or better - or just about any other browser):

<script type="text/javascript">
Array.prototype.numlet = function(){
var t = [], r = [], o = {}, i, p,
c = function(item){return isNaN(parseInt(item.toString(10)))? 9999999 : parseInt(item);};

for (i = this.length - 1; i > -1; --i)
if(o[c(this[i])]) o[c(this[i])].push(this[i]);
else o[c(this[i])] = [this[i]];

for (p in o) t.push(p), o[p].sort();

t.sort(function(a, b){return b - a;});

for (i = t.length - 1; i > -1; --i)
r = r.concat(o[t[i]]);

for (i = this.length - 1; i > -1; --i)
this[i] = r[i];
};
var x = ['2c','b','4z','3y','w','3c','4t','2a','9a', '3q'];
x.numlet();
</script>

It avoids the issue with numbers vs strings by making everything a string, and will work with arrays having entries like:

974gthw

and:

black

as well as with the typical sort of entries you mentioned.

To get the letter entries to come first in this version, just change the highlighted 9999999 to 0.

mhodgson
07-04-2008, 02:26 PM
Thanks for the help, it gives a good start for what I am trying to do.