4
var myArray = [
    '_aaaa_2013-09-25_ssss9.txt',
    '_aaaa_2013-09-25_ssss8.txt',
    '_aaaa_2013-09-26_ssss1.txt',
    '_aaaa_2013-09-25_ssss10.txt',
    '_aaaa_2013-09-26_ssss2.txt',
    '_aaaa_2013-09-25_ssss13.txt',
    '_aaaa_2013-09-25_ssss5.txt',
    '_aaaa_2013-09-25_ssss6.txt',
    '_aaaa_2013-09-25_ssss7.txt'
];

I need to sort the array by date and number.

Result should be

var result = [
    '_aaaa_2013-09-25_ssss5.txt',
    '_aaaa_2013-09-25_ssss6.txt',
    '_aaaa_2013-09-25_ssss7.txt',
    '_aaaa_2013-09-25_ssss8.txt',
    '_aaaa_2013-09-25_ssss9.txt',
    '_aaaa_2013-09-25_ssss13.txt',
    '_aaaa_2013-09-26_ssss1.txt',
    '_aaaa_2013-09-26_ssss2.txt'
];

I have tried below code.this will do the sort by date only but i need to sort by the number which is before '.txt'.How can i do this.

myArray.sort(function (a, b) {

    var timeStamp1 = a.substring(a.indexOf('_aaaa') + 6, a.indexOf('_ssss'));
    var timeStamp2 = b.substring(b.indexOf('_aaaa') + 6, b.indexOf('_ssss'));
    timeStamp1 = new Date(Date.UTC(timeStamp1[0], timeStamp1[1], timeStamp1[2]));
    timeStamp2 = new Date(Date.UTC(timeStamp2[0], timeStamp2[1], timeStamp2[2]));

    return (timeStamp1 > timeStamp2) ? 1 : (timeStamp2 > timeStamp1 ? -1 : 0);

});
Mike-O
  • 844
  • 1
  • 11
  • 16
sachin
  • 13,605
  • 14
  • 42
  • 55
  • @sachin: You can compare any YMD dates by number. You could compare your YYYY-MM-DD dates even as strings, but that's not needed here. And comparing numbers is trivial (search for it if you don't know it) – Bergi Sep 25 '13 at 18:35
  • I just tried the accepted solution in the link Ela posted and Bergi suggested for your use case, it sorted as you desire. – Arthur Weborg Sep 25 '13 at 18:39
  • @Bergi i have tried that but that is not working. – sachin Sep 26 '13 at 07:34
  • return (timeStamp1 > timeStamp2) ? 1 : 0; – frenchie Sep 26 '13 at 07:44
  • @frenchie - two problems with that. 1: A sort compare function needs to distinguish all three cases, greater, equal, or less, and return a positive number, 0, or a negative number. 2: Comparing the entire string will put `'_aaaa_2013-09-25_ssss13.txt'` in the wrong place, because it sorts in lexical order instead of using numeric order for the number part. – Michael Geary Sep 26 '13 at 08:00
  • 1
    Never ever duplicate your own question only because you didn't get an answer so far. Instead edit and improve your existing question. – hakre Sep 26 '13 at 08:41
  • This is not a programming question, this is just pasting in requirements and that's it. -1 – hakre Sep 26 '13 at 09:17
  • Related: http://stackoverflow.com/questions/15478954/javascript-sort-array-elements-string-with-numbers – Shog9 Oct 16 '13 at 14:09

4 Answers4

1

This worked for me.

myArray.sort(function (a, b) {
    var a_s = a.substring(0, a.indexOf('ssss') + 4);
    var a_n = a.substring(a.indexOf('ssss') + 4, a.indexOf('.txt'));
    var b_s = b.substring(0, b.indexOf('ssss') + 4);
    var b_n = b.substring(b.indexOf('ssss') + 4, b.indexOf('.txt'));
    if (a_s < b_s)
        return -1;
    if (a_s > b_s)
        return 1;
    return parseInt(a_n) - parseInt(b_n);
});

jsFiddle

azz
  • 5,852
  • 3
  • 30
  • 58
  • i tried this but i'm not getting exact output..first i need to sort by date then by number which is before '.txt'.Now its sorting only by date not by number – sachin Sep 26 '13 at 08:00
  • Check the jsFiddle link at the end. The panel on the (bottom-)right shows the output, it sorts by string then number, which is the same as date then number (so long as dates and months are padded left with `0`, e.g. `07` = July) – azz Sep 26 '13 at 08:08
  • Please move your answer over to http://stackoverflow.com/questions/19012468/javascript-sort-an-array-of-strings-that-can-contain-letters-numbers-and-dates – hakre Sep 26 '13 at 08:41
  • If you think it's a well answer (worth the action), move it to the dupe of the dupe. – hakre Sep 26 '13 at 09:50
1

You could do it like this:

var re = /^_aaaa_(\d\d\d\d-\d\d-\d\d)_ssss(\d+)\.txt$/;

var result = myArray.slice().sort( function( a, b ) {
    var aa = a.match(re), bb = b.match(re);
    return(
        aa[1] < bb[1] ? -1 :
        aa[1] > bb[1] ? 1 :
        aa[2] - bb[2]
    );
});

Note the use of .slice() to create a copy of the array. This can be omitted if you want to sort the original array in place. (Thanks to @DerFlatulator for the reminder!)

Michael Geary
  • 28,450
  • 9
  • 65
  • 75
  • Hi i tried this but im getting error in this line : aa[1] < bb[1] ? -1 : TypeError: Cannot read property '1' of null – sachin Sep 26 '13 at 07:51
  • 1
    What that error means is that the regular expression did not match the text in the array element. So it would seem your data must be different from what you posted in your question. If you paste your definition of `myArray` into the Chrome console and then paste my code above, the value of `result` will be what you were looking for. What is different in your data or code? – Michael Geary Sep 26 '13 at 07:55
  • @DerFlatulator my data is : cccc_aaaa_2013-09-26_ssss1.txt – sachin Sep 26 '13 at 08:53
  • Please note that this answer will modify `myArray` as well as store the result in `result`. If you want to make a shallow copy of the array, use something akin to `var result = myArray.slice().sort(...);` Also, why am I tagged in this answer? – azz Sep 26 '13 at 09:51
0

Sort by numeric value within strings.

This assumes:

  • numbers are integers
  • every string is different
  • dates may be sorted as numbers (year,month,day)

["aa_123","aa_13","aa_2","aa_22_bb_23","aa_22_bb_3"].sort( function ( a , b ) {

    var as = a.split(/([0-9]+)/); // splits string retaining separators
    var bs = b.split(/([0-9]+)/);
    var i,c = Math.min(as.length,bs.length);
    for ( i=0;i<c && as[i]===bs[i];++i ) ;
    var an = (i&1)?+as[i]:as[i]; // separators (digits) always at odd index
    var bn = (i&1)?+bs[i]:bs[i];
    return (an<bn)?-1:1; // assumes every string different

} );

result:

[
  "aa_2",
  "aa_13",
  "aa_22_bb_3",
  "aa_22_bb_23",
  "aa_123"
]
drawnonward
  • 53,459
  • 16
  • 107
  • 112
0

This, extracts the numbers from the given string, and puts a given weight on each numerical part. So you can sort it in any order with given priorities for Count, Day, Month, Year.

function weightedNumSort(myArray,weightNum,weightString) {    
    var WEIGHTS_NUM = weightNum || [1,2,4,3]; //[YEAR,MONTH,DAY,COUNT], You can pass an array with appropriate weights for the number at the given position in the text, e.g year is the first Number
    var WEIGHT_STRING = weightString || 1; //And a weight for the string value. If none get passed, default weights are used

        function weightedSum (a,b,i) {
            return ( a  +  b * ( WEIGHTS_NUM [i-1] || 1 ));
        }

    myArray = myArray.slice().sort(function (a, b) {
        var reg = /(\d+)/g //A regex to extract the numerical part

        var lNum = a.match(reg) //Extract the numerical parts we now have an array ["2013","09","26","2"]

        var rNum = b.match(reg)

        var delta = Array.apply(null,{length:lNum.length+1});
            delta [0] = 0; //add a 0 at the beginning, for convenience with the reduce function

        for (var i=0,j=lNum.length; i < j; i++) {
            var value = lNum[i] - rNum[i];
            value = ~~ (value / Math.abs (value)) // 1 for positive values, 0 for 0 , -1 for negative values, to make weighting easier
            delta[i+1] = value;
        }

        var weightedNumValue = delta.reduce (weightedSum) //Put a weight on the number parts.
        var weightedStrValue = WEIGHT_STRING * ( a > b ? 1 : a < b ? -1 : 0 )    
        return weightedNumValue + weightedStrValue //Add the weighted values and we have a positive or negative value with a correct weight on the numerical parts
    })
    return  myArray
}

Output

console.log (
   weightedNumSort (myArray)    
) /*
[
  "_aaaa_2013-09-25_ssss5.txt",
  "_aaaa_2013-09-25_ssss6.txt",
  "_aaaa_2013-09-25_ssss7.txt",
  "_aaaa_2013-09-25_ssss8.txt",
  "_aaaa_2013-09-25_ssss9.txt",
  "_aaaa_2013-09-25_ssss10.txt",
  "_aaaa_2013-09-25_ssss13.txt",
  "_aaaa_2013-09-26_ssss1.txt",
  "_aaaa_2013-09-26_ssss2.txt"
]*/

and a Fiddle

Moritz Roessler
  • 8,542
  • 26
  • 51