8
\$\begingroup\$

Below is my code. This is a function that will be applied as a sorting method to a grid based data set. The data in the column to be sorted can be stuff like: 123456, 123456:123444, and 12345:12359:139943. So far, I have tested it and it works, but I want to know in which situations might it not work, or if there is a way to optimize/improve the method in any way.

function SkuSorter(a, b, c) {
    // check if either input is a set
    var aMatch = a.match(/\:/g);
    var bMatch = b.match(/\:/g);

    // all items by default should be a regular sku, we'll change this later
    var aType = 0;
    var bType = 0;

    /* types;
     * 0 = regular sku
     * 1 = duo (12345:12345)
     * 2 = trio (1234:1234:1234)
     */

    // has the user sorted asc or desc? 
    var direction = c;


    // if 'a' is a set, determine if it is a duo or trio
    if (aMatch) {
        if (aMatch.length == 1) aType = 1;

        if (aMatch.length > 1) aType = 2;
    }

    // save as above
    if (bMatch) {
        if (bMatch.length == 1) bType = 1;

        if (bMatch.length > 1) bType = 2;
    }

    // if 'a' is a set and 'b' isn't, a should come before b (puts sets at the bottom)
    if (aType == 0 && bType != 0) {
        return -1 * direction;
    }

    // save as above, but viceversa.
    if (aType != 0 && bType == 0) {
        return 1 * direction;
    }

    // if both inputs are regular skus, do normal sort operation
    if (aType == 0 && bType == 0) {
        if (direction == -1) {
            return b - a;
        } else {
            return a - b;
        }
    }

    // if 'a' is a set and it is of higher order (i.e. trio > duo)
    if (aType > 0 && aType > bType) {
        return 1 * direction;
    }

    // same as above, but for 'b'
    if (bType > 0 && bType > aType) {
        return -1 * direction;
    }

    // if both inputs are sets
    if (aType > 0 && bType > 0) {

        //break up the individual pieces
        var aP = a.split(':');
        var bP = b.split(':');

        /*
         * The following conditions will compare:
         * The first chunk and sort them based on value
         * Then the second chunk, and if it is a trio, the third.
         */
        if (aP[0] > bP[0]) {
            return 1 * direction;
        }

        if (aP[0] < bP[0]) {
            return -1 * direction;
        }

        // second chunk
        if (aP[1] > bP[1]) {
            return 1 * direction;
        }

        if (aP[1] < bP[1]) {
            return -1 * direction;
        }

        // third chunk
        if (aType > 1 && bType > 1) {
            if (aP[2] > bP[2]) {
                return 1 * direction;
            }

            if (aP[2] < bP[2]) {
                return -1 * direction;
            }
        }
    }
}

Expected behavior:

Before:

1654110
1574698
1189364
1229764
1700004
310425
1626613
36509
1676618
1676832
1536622
1749548
36509:310444
3199:44999:34000
3199:45000:34000
3199:45000:34111
1874361
1551225
1581271
1626076
36509:310425
1676816
1676824

After:

36509
310425
1189364
1229764
1536622
1551225
1574698
1581271
1626076
1626613
1654110
1676618
1676816
1676824
1676832
1700004
1749548
1874361
36509:310425
36509:310444
3199:44999:34000
3199:45000:34000
3199:45000:34111
\$\endgroup\$
  • 1
    \$\begingroup\$ Can you give an example of some numbers you want to be sorted and what you would expect the result to be? \$\endgroup\$ – Jivings Apr 16 '14 at 17:56
  • \$\begingroup\$ Added to original post \$\endgroup\$ – sk0093a Apr 16 '14 at 18:09
3
\$\begingroup\$

@Flambino was a bit faster :

function sortSKU( a, b  )
{
    var aParts = a.split( ':' ),
        bParts = b.split( ':' ),
        partCount = aParts.length,
        i;

    if( aParts.length != bParts.length )
        return aParts.length - bParts.length;

    for( i = 0 ; i < partCount ; i++ )
    {
      if( aParts[i] != bParts[i] )
        return +aParts[i] - +bParts[i];
    }
    //Exactly the same
    return 0;
}

console.log( data.sort( sortSKU )  );

As Flambino said, use .reverse() to sort one way or another. Also this function will sort 123 prior to 2:2 if such a case can occur.

If you need the 'c'

function sortingCallback( array, direction ){

  if( direction == 'whatever ascending is' ){
    return array.sort( sortSKU );
  }

  return array.sort( sortSKU ).reverse();
}
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ FYI, the 'c' in my original code is the direction of the sort passed by jqGrid(jQuery Grid). I would assume that I can just multiple the return statements by 'c' (in your code) to switch them to ascending or descending? \$\endgroup\$ – sk0093a Apr 16 '14 at 18:31
  • \$\begingroup\$ Updated my answer with what you could do \$\endgroup\$ – konijn Apr 16 '14 at 18:36
  • \$\begingroup\$ My code doesn't actually do the trick, so I'm deleting it. Maybe it'll come back later if I find a solution. But that'll just be for my own sake; you've got this one, konijn \$\endgroup\$ – Flambino Apr 16 '14 at 18:43
  • \$\begingroup\$ @Flambino the comparing of arrays was very smart, I didn't know you could do that. \$\endgroup\$ – konijn Apr 16 '14 at 18:45
  • 1
    \$\begingroup\$ multiplying the return aParts.. lines by c (-1 desc, 1 asc) seemed to do the trick. I did this in order to reverse whatever result it might have come up with. Thoughts? \$\endgroup\$ – sk0093a Apr 16 '14 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.