JSFiddle - React, Tailwind, and code Playground

by cdaringe

HTML

<script src="//cdn.jsdelivr.net/es6-promise/0.1.1/promise.js"></script>
<h1>Sensible String-o-Numeric Sorter</h1>
<p>The following sorts strings that are mixed with numbers by actually factoring in the value of the number s.t. the sort order reflects that value.</p>

<p>If asked to sort the following:</p>
<ol>
    <li>Week 1</li>
    <li>Week 10</li>
    <li>Week 2</li>
</ol>

<p>A normal js array sort will output results in THAT order.  This sorter actually places the numbers in order.  Play with the test data!</p>

<div class="log">
    <h3>Log</h3>
    <ul id="log"></ul>
</div>

CSS

.log{
    background-color:#FFEAB6;
    border-radius:5px;
    font-family:"Helvetica", Arial;
    padding: 10px;
}

JavaScript

function post(txt){
    var newItem = document.createElement("li");
    newItem.innerHTML += txt;
    document.getElementById('log').appendChild(newItem);
}

// split @numbers credit: http://jsfiddle.net/5WJ9v/
items = ["Week 1", "27str", "22str", "2str", 3, "Week 10", 1, "Week 2", 0, "week 11", 150, "1", -43.3, "0", "Week 10 POST-JUNK -32", "Week 103 POST-JUNK", "Week 103 POST-JUNK 10", "Week 103 POST-JUNK 2"];
// items = ["27str", "2str", "22str"];
items.sort(function (a, b) {
    if (!isNaN(a) && !isNaN(b)) return a - b;
    else if (!isNaN(a) && isNaN(b)) return -1;
    else if (isNaN(a) && !isNaN(b)) return 1;
    else if (typeof a === "string" && typeof b === "string") {
        var regex = /(\d+)/g,
            aSplit = a.split(regex),
            bSplit = b.split(regex),
            aBlock, bBlock,
            aBlockNum, bBlockNum;
        for (var ndx = 0; ndx < aSplit.length; ++ndx) {
            if (bSplit[ndx] !== undefined) {
                aBlock = aSplit[ndx];
                bBlock = bSplit[ndx];
            } else {
                return 1; // b is shorter, thus put it first
            }

            if (aBlock !== bBlock) {
                // Check & compare numeric
                aBlockNum = parseInt(aBlock,10);
                bBlockNum = parseInt(bBlock,10);
                if (!isNaN(aBlockNum) && !isNaN(bBlockNum)) return aBlockNum - bBlockNum;
                if (!isNaN(aBlockNum) && isNaN(bBlockNum)) return -1;
                if (isNaN(aBlockNum) && !isNaN(bBlockNum)) return 1;

                // String compare
                if (aBlock < bBlock) return -1;
                if (aBlock > bBlock) return 1;
                // if blocks ===, proceed to next block
            }
        }
        return 0; // strings were equal
    } else {
        throw new Error("Invalid data passed to be sorted!");
    }
});

items.forEach(post);

console.dir(items);