Search code examples
javascriptsortingdate-sorting

Sorting by datetime substring after being sorted by asset code substring JAVASCRIPT


I would like to sort an array of strings:

J01171 01/02/2013 18:12:43 J01171 Bath Rd Ipswich Isolated by OTU Fault   
J01171 01/02/2013 18:42:32 J01171 Bath Rd Ipswich Reconnected   
J01171 01/11/2012 08:04:34 J01171 Bath Rd Ipswich Isolated by OTU Fault   
J01171 01/11/2012 08:04:47 J01171 Bath Rd Ipswich Reconnected   
J01171 02/01/2013 15:46:22 J01171 Bath Rd Ipswich Isolated by OTU Fault   
J01171 02/01/2013 15:46:36 J01171 Bath Rd Ipswich Reconnected  
J01181 09/02/2013 00:43:00 J01181 BathRd LeighRd Isolated by OTU Fault    
J01181 09/02/2013 00:47:57 J01181 BathRd LeighRd Reconnected    
J01181 10/12/2012 13:13:13 J01181 BathRd LeighRd Isolated by Fault   
J01181 10/12/2012 15:30:01 J01181 BathRd LeighRd Reconnected  

Right now as I sort the array of strings with usual array.sort() JavaScript function, it sorts all lines as strings, so numbers come in numeric order, not as the date. What I want is to keep sorting for asset codes 'J01171', 'J01181', etc. as usual strings, but dates coming after the asset codes I would like to sort like real date time in format dd/mm/yyyy hh:mm:ss, not like a piece of string. Basically, the output I want is:

J01171 01/11/2012 08:04:34 J01171 Bath Rd Ipswich Isolated by OTU Fault   
J01171 01/11/2012 08:04:47 J01171 Bath Rd Ipswich Reconnected   
J01171 02/01/2013 15:46:22 J01171 Bath Rd Ipswich Isolated by OTU Fault   
J01171 02/01/2013 15:46:36 J01171 Bath Rd Ipswich Reconnected  
J01171 01/02/2013 18:12:43 J01171 Bath Rd Ipswich Isolated by OTU Fault  
J01171 01/02/2013 18:42:32 J01171 Bath Rd Ipswich Reconnected   
J01181 10/12/2012 13:13:13 J01181 BathRd LeighRd Isolated by Fault    
J01181 10/12/2012 15:30:01 J01181 BathRd LeighRd Reconnected     
J01181 09/02/2013 00:43:00 J01181 BathRd LeighRd Isolated by OTU Fault     
J01181 09/02/2013 00:47:57 J01181 BathRd LeighRd Reconnected

Solution

  • The .sort() function allows you to supply a callback function that knows how to compare any two items in the array according to whatever rules you care to implement.

    The easiest way that comes to mind to achieve your requirement is just to replace the dd/mm/yyyy date format with yyyymmdd, because then a standard alphanumeric sort will work and there's no need to muck around actually creating date objects or anything. (This replacement doesn't actually change the items in the array, I just mean do a replacement in some working variables for purposes of a sort comparison.) So:

    var arr = [
        "J01171 01/02/2013 18:12:43 J01171 Bath Rd Ipswich Isolated by OTU Fault",
        "J01171 01/02/2013 18:42:32 J01171 Bath Rd Ipswich Reconnected",
        etc.
    ];
    
    var regex = /^([^ ]+ )(\d\d)\/(\d\d)\/(\d{4})/;
    
    arr.sort(function(a, b) {
        return a.replace(regex,"$1$4$3$2").localeCompare(b.replace(regex,"$1$4$3$2"));
    });
    

    Demo: http://jsfiddle.net/NuWty/

    The regex-based replacement used within the sort() callback turns each item to be compared into this format:

    J01171 20130201 18:12:43 J01171 Bath Rd Ipswich Isolated by OTU Fault
    

    I then use .localeCompare() to do a standard alphanumeric comparison on each pair of items. A longer but perhaps clearer way to do that would be:

    arr.sort(function(a, b) {
        a = a.replace(regex,"$1$4$3$2");
        b = b.replace(regex,"$1$4$3$2");
        if (a > b)
           return 1;
        else if (a < b)
           return -1;
        else
           return 0;
    });