3

how do I sort an array

var arr = new Array("word_12", "word_59", "word_17");

so that I get

["word_12", "word_17", "word_59"]

Thanks!

user1054134
  • 443
  • 1
  • 4
  • 21

4 Answers4

4

you need to write a sort method (you can write any that you like) which splits the string on the _ and uses the second part as a numeric sort value.

​    function sortOnNum(a,b){
         //you'll probably want to add a test to make sure the values have a "_" in them and that the second part IS a number, and strip leading zeros, if these are possible
         return (a.split("_")[1] * 1 > b.split("_")[1] * 1)? 1:-1;// I assume the == case is irrelevant, if not, modify the method to return 0 for ==
    }

    var ar = new Array ("foo_1", "foo_19", "foo_3", "foo_1002");

ar.sort(sortOnNum); //here you pass in your sorting function and it will use the values in the array against the arguments a and b in the function above

alert(ar); // this alerts "foo_1,foo_3,foo_19,foo_1002"

Here's a fiddle: http://jsfiddle.net/eUvbx/1/

Yevgeny Simkin
  • 27,946
  • 39
  • 137
  • 236
  • 2
    While booleans find some success in sort methods, the [correct response](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort#Description) is a positive or negative number, or 0. I used to use booleans as well, until I got called out on it ;) – Sampson Jun 06 '12 at 20:30
  • @JonathanSampson: on the "correct response" link there is an assertion that in lexicographical order 80 comes before 9 but it is nowhere explained why? The link http://oeis.org/wiki/Orderings#Lexicographic_order shows the opposite – user1054134 Jun 08 '12 at 09:53
  • @Jonathan Sampson I realized that I need to sort key value pairs. Could you check out my question at (http://stackoverflow.com/questions/10946880/sort-a-dictionary-on-word-number-values/10946984#10946984) ? – user1054134 Jun 08 '12 at 10:27
2

The following assumes your number will always be at the very end of the string. Note, I've added a few additional examples into the array to demonstrate the differing formats this can work with:

var numbers = ["word_12", "word_59", "word_17", "word23", "28", "I am 29"];

numbers.sort(function(a,b){
    return a.match(/\d+$/) - b.match(/\d+$/);
});

Which results in:

["word_12", "word_17", "word23", "28", "I am 29", "word_59"]
Sampson
  • 265,109
  • 74
  • 539
  • 565
  • @Jonathan, does this not suffer from the risk of there appearing a number in his "word" part? – Yevgeny Simkin Jun 06 '12 at 20:40
  • @Dr.Dredel It does require his values to appear in the same format he's presented here. If they don't, problems could arise. That being said, I've made a modification that will only match numbers at the *end* of the value. – Sampson Jun 06 '12 at 20:41
  • @JonathanSampson, cool, and as I said in my example, there's probably a need to verify that the number is a number and isn't prefixed. But yeah.. very nice. – Yevgeny Simkin Jun 06 '12 at 20:44
  • @Dr.Dredel What do you mean by the number being prefixed? – Sampson Jun 06 '12 at 20:48
  • @JonathanSampson, well if it's 03 or some such – Yevgeny Simkin Jun 06 '12 at 20:53
  • @JonathanSampson, I guess I'm not clear on what the interpreter will do when faced with having to modify strings into numbers in order to perform a subtraction on them. parseInt treats numbers that start with 0 as octal, I'm sure it would only take a moment to run a test and see how this works, but I'm preferring to just speculate and be mildly perplexed by it. – Yevgeny Simkin Jun 06 '12 at 21:00
  • @Dr.Dredel `parseInt` treats strings which begin with 0 as octal, unless you provide the appropriate radix. `["012"] - 6` is eventually converted to `12 - 6`, but only as long as the array has one value. You can open up your console and run `["012"] - 6` and see the output. – Sampson Jun 06 '12 at 22:51
0

just in case there are numbers and underscores in the word (which are quite legal word characters by javascript word definition:

arr.sort(function(_1, _2)
{
    return +_1.substr(_1.lastIndexOf("_")+1)-_2.substr(_2.lastIndexOf("_")+1);
});
panda-34
  • 4,089
  • 20
  • 25
0

Here's code for the general case:

natcmp = function(a, b) {
    var aa = [], bb = [];

    (a + "").replace(/(\d+)|(\D+)/g, function($0, $1, $2) { aa.push($2 || Number($1)) });
    (b + "").replace(/(\d+)|(\D+)/g, function($0, $1, $2) { bb.push($2 || Number($1)) })

    var la = aa.length, lb = bb.length;

    for (var i = 0; i < Math.max(la, lb); i++) {
        if (i >= lb) return 1;
        if (i >= la) return -1;
        if (aa[i] > bb[i]) return 1;
        if (aa[i] < bb[i]) return -1;
    }

    return 0;
}

Example:

var x = ["word_12", "word_59", "ford_1a", "ford_12a", "ford_2a", "word_0", "word_"];
x.sort(natcmp)

# ["ford_1a", "ford_2a", "ford_12a", "word_", "word_0", "word_12", "word_59"]

This is called "natural sorting".

georg
  • 211,518
  • 52
  • 313
  • 390