Search code examples
javascriptassociative-arraysorting

Javascript natural sort array/object and maintain index association


I have an array of items as follows in Javascript:

var users = Array();

users[562] = 'testuser3';
users[16] = 'testuser6';
users[834] = 'testuser1';
users[823] = 'testuser4';
users[23] = 'testuser2';
users[917] = 'testuser5';

I need to sort that array to get the following output:

users[834] = 'testuser1';
users[23] = 'testuser2';
users[562] = 'testuser3';
users[823] = 'testuser4';
users[917] = 'testuser5';
users[16] = 'testuser6';

Notice how it is sorted by the value of the array and the value-to-index association is maintained after the array is sorted (that is critical). I have looked for a solution to this, tried making it, but have hit a wall.

By the way, I am aware that this is technically not an array since that would mean the indices are always iterating 0 through n where n+1 is the counting number proceeding n. However you define it, the requirement for the project is still the same. Also, if it makes a difference, I am NOT using jquery.


Solution

  • Using the ideas from the comments, I came up with the following solution. The naturalSort function is something I found on google and I modified it to sort a multidimensional array. Basically, I made the users array a multidimensional array with the first index being the user id and the second index being the user name. So:

    users[0][0] = 72;
    users[0][1] = 'testuser4';
    users[1][0] = 91;
    users[1][1] = 'testuser2';
    users[2][0] = 12;
    users[2][1] = 'testuser8';
    users[3][0] = 3;
    users[3][1] = 'testuser1';
    users[4][0] = 18;
    users[4][1] = 'testuser7';
    users[5][0] = 47;
    users[5][1] = 'testuser3';
    users[6][0] = 16;
    users[6][1] = 'testuser6';
    users[7][0] = 20;
    users[7][1] = 'testuser5';
    

    I then sorted the array to get the following output:

    users_sorted[0][0] = 3;
    users_sorted[0][1] = 'testuser1';
    users_sorted[1][0] = 91;
    users_sorted[1][1] = 'testuser2';
    users_sorted[2][0] = 47;
    users_sorted[2][1] = 'testuser3';
    users_sorted[3][0] = 72;
    users_sorted[3][1] = 'testuser4';
    users_sorted[4][0] = 20;
    users_sorted[4][1] = 'testuser5';
    users_sorted[5][0] = 16;
    users_sorted[5][1] = 'testuser6';
    users_sorted[6][0] = 18;
    users_sorted[6][1] = 'testuser7';
    users_sorted[7][0] = 12;
    users_sorted[7][1] = 'testuser8';
    

    The code to do this is below:

    function naturalSort(a, b) // Function to natural-case insensitive sort multidimensional arrays by second index
    {
    
        // setup temp-scope variables for comparison evauluation
        var re = /(-?[0-9\.]+)/g,
            x = a[1].toString().toLowerCase() || '',
            y = b[1].toString().toLowerCase() || '',
            nC = String.fromCharCode(0),
            xN = x.replace( re, nC + '$1' + nC ).split(nC),
            yN = y.replace( re, nC + '$1' + nC ).split(nC),
            xD = (new Date(x)).getTime(),
            yD = xD ? (new Date(y)).getTime() : null;
        // natural sorting of dates
        if ( yD )
            if ( xD < yD ) return -1;
            else if ( xD > yD ) return 1;
        // natural sorting through split numeric strings and default strings
        for( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) {
            oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];
            oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];
            if (oFxNcL < oFyNcL) return -1;
            else if (oFxNcL > oFyNcL) return 1;
        }
        return 0;
    }
    
    // Set values for index
        var users = Array();
        var temp = Array();
    
        users.push(Array('72', 'testuser4'));
        users.push(Array('91', 'testuser2'));
        users.push(Array('12', 'testuser8'));
        users.push(Array('3', 'testuser1'));
        users.push(Array('18', 'testuser7'));
        users.push(Array('47', 'testuser3'));
        users.push(Array('16', 'testuser6'));
        users.push(Array('20', 'testuser5'));
    
    // Sort the array
        var users_sorted = Array();
        users_sorted = users.sort(naturalSort);