-2

I have the following array and I would like to trim each entry down to just the number and one letter then order them numerically.

["10Regular", "18Regular", "14Long", "14Regular", "10Long", "16Long", "12Long", "20Regular", "16Regular", "12Regular", "18Long"]

I have tried playing about with regular expressions but am finding it difficult

Rhi
  • 29
  • 6
  • Is every numeric entry of 2 digits? – Shrinivas Shukla Jul 02 '15 at 19:12
  • _“I would like to trim each entry down to just the number and one letter then order them numerically”_ – if you want to include that one letter in the sorting order, then you _don’t_ want to sort (purely) numerically. Besides, this would be one of the rather simple cases of regular expressions – so at least show us what you have tried. – CBroe Jul 02 '15 at 19:15
  • See [this post](http://stackoverflow.com/questions/4736/learning-regular-expressions), show some effort please. – ShellFish Jul 02 '15 at 19:18

3 Answers3

2
var arr = [
    "10Regular", "18Regular", "14Long", "14Regular",
    "10Long", "16Long", "12Long", "20Regular",
    "16Regular", "12Regular", "18Long"
];

var trimmedAndSorted = arr.map(function(e) {
    return e.replace(/(\d+[a-z]).*/i, '$1');
}).sort();

Got a downvote so I assume there is a syntax error, but I tested with a JSFiddle and it appears to work.

Sean Bright
  • 118,630
  • 17
  • 138
  • 146
1

If you just want to sort them using the numbers in front, regardless of the letters that come after them, given arr as you array:

arr.map(function(entry){
  // extract the number and first letter as [number, letter]
  return entry.match(/^(\d+)(.{1})/).slice(1)
}).sort(function(a, b){
  // Sort the array by the number part 
  return +a[0] - +b[0];
}).map(function(entry){
  // Join the two parts 
  return entry.join('');
});

// ["10R", "10L", "12R", "12L", "14L", "14R", "16L", "16R", "18R", "18L", "20R"]
Joseph
  • 117,725
  • 30
  • 181
  • 234
1

Define a sorting function, that takes functions for augmented sorting

My favorite sorting function (which is more versatile than needed for just this task) can sort arrays of values or objects of any nested depth and accepts an optional function for priming the value, and an optional function for secondary "then by" sorting.

Sort by, then by function:

var by = function (path, reverse, primer, then) {

        // Light weight json deep access
    var get = function (obj, path) {
            if (path) {
                path = path.split('.');
                for (var i = 0, len = path.length - 1; i < len; i++) {
                    obj = obj[path[i]];
                };
                return obj[path[len]];
            }
            return obj;
        },

        // Invokes primer function if provided
        prime = function (obj) {
            return primer ? primer(get(obj, path)) : get(obj, path);
        };

    // Actual sorting function to be returned to native .sort method
    return function (a, b) {
        var A = prime(a),
            B = prime(b);

        return (
            (A < B) ? -1 :
            (A > B) ?  1 :
            // If A == B, then sort by supplemental 'by' function received as 'then' 
            (typeof then === 'function') ? then(a, b) : 0
        ) * [1,-1][+!!reverse];
    };
};

Acknowledgement: The above function is my fork of a function that I found as a response to this Stack Overflow question.

Basic usage:

array.sort(
    by(path[, reverse[, primer[, then]]])
);

Example usage with your array:

/* THE ARRAY */
var arr = ["10Regular", "18Regular", "14Long", "14Regular", "10Long", "16Long", "12Long", "20Regular", "16Regular", "12Regular", "18Long"];

/* THE EXAMPLE */
arr.sort(
    by(null, false,
        function (x) { // Primer
            var y = x.substr(0,2);
            return parseFloat(y);
        },
        by(null, false, // Secondary "then by" sort
            function (x) { // Primer
                var y = x.substr(2);
                return y;
            }
        )
    )
);

The idea here is to split your value into the two parts by which you wish to sort it.

Assuming that your string values will always begin with two-digit numbers, we define a priming function that uses .substr to return just the first two digits. This primed value gets passed along to the return function in the closure just for the comparison, while preserving the original value to be sorted.

We then define a secondary "then by" sorting function which takes the same form as the first (you just pass in another instance of by()). In this secondary by() function, we define another priming function that uses .substr again to return the second half of the string.

Complete working example with output:

/* THE FUNCTION */
var by = function (path, reverse, primer, then) {
  
        // Light weight json deep access
    var get = function (obj, path) {
            if (path) {
                path = path.split('.');
                for (var i = 0, len = path.length - 1; i < len; i++) {
                    obj = obj[path[i]];
                };
                return obj[path[len]];
            }
            return obj;
        },
        
        // Invokes primer function if provided
        prime = function (obj) {
            return primer ? primer(get(obj, path)) : get(obj, path);
        };
    
    // Actual sorting function to be returned to native .sort method
    return function (a, b) {
        var A = prime(a),
            B = prime(b);
        
        return (
            (A < B) ? -1 :
            (A > B) ?  1 :
            // If A == B, then sort by supplemental 'by' function received as 'then' 
            (typeof then === 'function') ? then(a, b) : 0
        ) * [1,-1][+!!reverse];
    };
};

/* THE ARRAY */
var arr = ["10Regular", "18Regular", "14Long", "14Regular", "10Long", "16Long", "12Long", "20Regular", "16Regular", "12Regular", "18Long"];

/* THE EXAMPLE */
arr.sort(
    by(null, false,
        function (x) {
            var y = x.substr(0,2);
            return parseFloat(y);
        },
        by(null, false,
            function (x) {
                var y = x.substr(2);
                return y;
            }
        )
    )
);

// Output
var t1 = document.getElementById('t1');
t1.innerHTML += '<caption>Sort by, then by</caption>';
for (var i = 0; i < arr.length; i++) {
    t1.innerHTML += '<tr><td>' + arr[i] + '</td></tr>';
}
html { font: normal 62.5% Arial, sans-serif; }
body { padding: 10px; }
table {
    font-size: 1.3em;
    margin-bottom: 18px;
    width: 50%;
    border: none;
}
table caption {
    font-weight: bold;
    font-size: 1.5rem;
}
table td {
    color: #333;
    padding: 9px;
    vertical-align: middle;
    text-align: left;
    line-height: 1em;
    border-bottom: 1px solid #bcbec0;
    font: normal 1.3em monospace;
}
<table id="t1"></table>
Community
  • 1
  • 1
gfullam
  • 11,531
  • 5
  • 50
  • 64