Convert array of numbers into range groups.

by mberkom

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.8.0/lodash.min.js"></script>
<p>Converts an array of integers into an array of groups of integers based on sequential distances between numbers.</p>
<br />
<p>Dependent on <a href="http://lodash.com/">Lo-Dash</a></p>
<br />
<p>[1,2,3,4,6,8,10] becomes: </p>
<br />
<pre>
    [<span id="content"></span>]
</pre>

JavaScript

var rangeGroups = function(unsortedArray) {
    var array = _.sortBy(unsortedArray, function (item) {
            return parseInt(item, 10);
        }),
        groups = [],
        distancesBack = [],
        distancesForward = [];
        
    _(array).forEach(function (currentItem, index) {
        var lastGroup = _.last(groups);

        var previousItem = array[index - 1],
            distanceBack = currentItem - previousItem,
            nextItem = array[index + 1],
            distanceForward = (nextItem) ? nextItem - currentItem : null,
            // Applies the the third-last items
            // if (distanceBack === distancesBack[0])
            // - The current item's distance back is equal to the previous item's
            // if (distanceBack !== distancesBack[0] && distanceForward === distancesForward[0] && (distancesBack[1] && distancesBack[0] != distancesBack[1]))
            // - The current item's distance back is not equal to the previous item's
            // - The current item's distance forward is equal to the previous item's
            // - There is a second distance back and the first distance back is not equal to the second distance back.
            ifDistancesBack = distancesBack[0] && (distanceBack === distancesBack[0] || (distanceBack !== distancesBack[0] && distanceForward === distancesForward[0] && (distancesBack[1] !== undefined && distancesBack[0] != distancesBack[1]))),
            // Applies only to the second item in the list
            // If its distance forward is the same as the first item's 
            // distance forward, add it to the existing group
            ifNotDistancesBack = !distancesBack[0] && distanceForward === distancesForward[0];
        
        if (index > 0 && (ifDistancesBack || ifNotDistancesBack)) {
            // Add to last group if...
            // "previousDistanceBack === null" - we haven't yet recorded a previousDistanceBack
            // "distanceBack === previousDistanceBack" - the...