HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Getting all number from a String like this "1,2,5-9"

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thisnumberallgettinglikefromstring

Problem

I need to get the numbers in a string like "1,2,5-9", the function should return a list with these values ​​[1,2,5,6,7,8,9]

Here's what I did. Is this the best way or there's something simpler/better?

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function getNumbers(stringNumbers) {
  var nums = [];
  var list1 = stringNumbers.split(",");
  var length = list1.length;
  for(var i = 0; i  max){
          var min_ref = min;
          min = max;
          max = min_ref;
        }

        while(min <= max) {
          nums.push(min);
          min++
        };
      }
    } else {
      if(isNumber(number)) {
        nums.push(parseInt(number));
      }
    }
  }

  //edit to sort list at the end
  return nums.sort(function(a,b){return a - b});
};

Solution

Well, here's my version that's benchmarked across different browsers. Might need some improvement (currently finding shortcuts for the isNumber), but works as marketed:

function getNumbers(stringNumbers) {

    //personal preference, but I got this handy tip from the internet that

    //if you had assignments, better if they are individually var'ed
    var nums = [];
    var entries = stringNumbers.split(',');
    var length = entries.length;

    //for variabes that don't, comma separated
    var i, entry, low, high, range;

    for (i = 0; i < length; i++) {
        entry = entries[i];

        //shortcut for testing a -1
        if (!~entry.indexOf('-')) {
            //absence of dash, must be a number
            //force to a number using +
            nums.push(+entry);
        } else {
            //presence of dash, must be range
            range = entry.split('-');

            //force to numbers
            low = +range[0];
            high = +range[1];

            //XOR swap, no need for an additional variable. still 3 steps though
            //http://en.wikipedia.org/wiki/XOR_swap_algorithm
            if(high < low){
              low = low ^ high;
              high = low ^ high;
              low = low ^ high;
            }

            //push for every number starting from low
            while (low <= high) {
                nums.push(low++);
            }
        }
    }

    //edit to sort list at the end
    return nums.sort(function (a, b) {
        return a - b;
    });
}


Here's another version, which is slightly slower (the V2) since I added the additional number checks which the one above didn't but more conformant to the specification of the question.

var getNumbers = (function () {

    //we create a closure so as not to expose some of our utility functions

    function isNumber(n) {
        //we check isFinite first since it will weed out most of the non-numbers
        //like mixed numbers and strings, which parseFloat happily accepts
        return isFinite(n) && !isNaN(parseFloat(n));
    }

    //let's get this one out as well
    //the simple sort() wouldn't work so instead we provide a sorter
    function sorterFunction(a, b) {
        return a - b;
    }

    //getNumbers should be this function
    return function (stringNumbers) {

        //variable declaration format is personal preference
        //but I prefer having declarations with assignments have individual vars
        //while those that have no assignments as comma separated
        var i, range, low, high, entry;

        //an added bonus, " and ' are the same in JS, but order still applies
        //I prefer to use ' since it's cleaner
        var entries = stringNumbers.split(','); 
        var length = entries.length;
        var nums = [];

        for (i = 0; i < length; ++i) {
            entry = entries[i];

            if (isNumber(entry)) {
                //we check if the entry itself is a number. If it is, then we push it directly.
                //an additinal advantage is that negative numbers are valid
                nums.push(+entry);
            } else {

                //if not a number, probably it had the - and not being a negative number
                //only here do we split after we determined that the entry isn't a number
                range = entry.split('-');

                //check if what we split are both numbers, else skip
                if (!isNumber(range[0]) || !isNumber(range[1])) continue;

                //force both to be numbers
                low = +range[0];
                high = +range[1];

                //since we are dealing with numbers, we could do an XOR swap
                //which is a swap that doesn't need a third variable
                //http://en.wikipedia.org/wiki/XOR_swap_algorithm
                if (high < low) {
                    low = low ^ high;
                    high = low ^ high;
                    low = low ^ high;
                }

                //from low, we push up to high
                while (low <= high) {
                    nums.push(low++);
                }
            }
        }
        return nums.sort(sorterFunction);
    }
}());

Code Snippets

function getNumbers(stringNumbers) {

    //personal preference, but I got this handy tip from the internet that

    //if you had assignments, better if they are individually var'ed
    var nums = [];
    var entries = stringNumbers.split(',');
    var length = entries.length;

    //for variabes that don't, comma separated
    var i, entry, low, high, range;

    for (i = 0; i < length; i++) {
        entry = entries[i];

        //shortcut for testing a -1
        if (!~entry.indexOf('-')) {
            //absence of dash, must be a number
            //force to a number using +
            nums.push(+entry);
        } else {
            //presence of dash, must be range
            range = entry.split('-');

            //force to numbers
            low = +range[0];
            high = +range[1];

            //XOR swap, no need for an additional variable. still 3 steps though
            //http://en.wikipedia.org/wiki/XOR_swap_algorithm
            if(high < low){
              low = low ^ high;
              high = low ^ high;
              low = low ^ high;
            }

            //push for every number starting from low
            while (low <= high) {
                nums.push(low++);
            }
        }
    }

    //edit to sort list at the end
    return nums.sort(function (a, b) {
        return a - b;
    });
}
var getNumbers = (function () {

    //we create a closure so as not to expose some of our utility functions

    function isNumber(n) {
        //we check isFinite first since it will weed out most of the non-numbers
        //like mixed numbers and strings, which parseFloat happily accepts
        return isFinite(n) && !isNaN(parseFloat(n));
    }

    //let's get this one out as well
    //the simple sort() wouldn't work so instead we provide a sorter
    function sorterFunction(a, b) {
        return a - b;
    }

    //getNumbers should be this function
    return function (stringNumbers) {

        //variable declaration format is personal preference
        //but I prefer having declarations with assignments have individual vars
        //while those that have no assignments as comma separated
        var i, range, low, high, entry;

        //an added bonus, " and ' are the same in JS, but order still applies
        //I prefer to use ' since it's cleaner
        var entries = stringNumbers.split(','); 
        var length = entries.length;
        var nums = [];

        for (i = 0; i < length; ++i) {
            entry = entries[i];

            if (isNumber(entry)) {
                //we check if the entry itself is a number. If it is, then we push it directly.
                //an additinal advantage is that negative numbers are valid
                nums.push(+entry);
            } else {

                //if not a number, probably it had the - and not being a negative number
                //only here do we split after we determined that the entry isn't a number
                range = entry.split('-');

                //check if what we split are both numbers, else skip
                if (!isNumber(range[0]) || !isNumber(range[1])) continue;

                //force both to be numbers
                low = +range[0];
                high = +range[1];

                //since we are dealing with numbers, we could do an XOR swap
                //which is a swap that doesn't need a third variable
                //http://en.wikipedia.org/wiki/XOR_swap_algorithm
                if (high < low) {
                    low = low ^ high;
                    high = low ^ high;
                    low = low ^ high;
                }

                //from low, we push up to high
                while (low <= high) {
                    nums.push(low++);
                }
            }
        }
        return nums.sort(sorterFunction);
    }
}());

Context

StackExchange Code Review Q#26125, answer score: 7

Revisions (0)

No revisions yet.