Character range generator I am working on trying to create a range function in JavaScript that imitates PERL's 'a'..'zz'.

which expands to:


a->z
aa->az
ba->bz
...
za->zz


And so on for every extra character you add to the end of the range( e.g zzz .... ).

I have a working implementation, However, I think that there is a more efficient - and perhaps more idiomatic - solution.

There are two things I would like answers to address:


I would like to reduce the code size - this seems like too many lines for the problem that it solves.
I would like improve the performance - the implementation that I have is very slow for any end string > 5 characters long.




function charRange( start, end ) {
  var current = start;
  var range   = [];

  range.push( current ); //Put the start directly into the range.
  if ( typeof start === typeof end &amp;&amp;
     ( typeof start === "string" )) {
    if ( typeof end !== "string" ) {
        console.log( "ERROR: start and end must both be Strings!" );
    }
  }

  while ( !stringEqual(current.split(""), end.split("")) ) {
    current = next(current);
    range.push( current );
    // process.exit();
  }

  return range;


  function stringEqual( chars, testChars ) {
    var isEqual = 1;
    var sum = 0;
    var testSum = 0;
    var i = 0;
    while ( i &lt; testChars.length ) {
        // console.log(chars);
        // console.log(testChars);
        // console.log(i);

        if ( isEqual &amp;&amp; chars[i] !== testChars[i] ) {
            isEqual = 0;
        };
        if ( chars[i] ) {
            sum     += chars[i].charCodeAt(0);
        };
        testSum += testChars[i].charCodeAt(0);
        i++;
    }

    // console.log( sum + " " + testSum );
    return isEqual || (sum &lt; testSum ? 0 : 1);
  }

  function allAreZ( string ) {
    var found = 1;
    var i     = 0;
    while ( i &lt; string.length ) {
        if ( string[i] !== "z" ) {
            found = 0;
            break;
        }
        i++;
    }

    return found;
  }

  function findIncrementIndex( item ) {
    var index = item.indexOf("z");
    var i     = 0;

    while (index === 0) {
        i++;
        index = item.substr(i).indexOf("z");
    }

    index += i;

    return index;
  }

  function next( item ) {
    if ( typeof item === "number" ) {
        return item++;
    } else if ( typeof item === "string" ) {
        var lastCharCode = item.charCodeAt( item.length -1 );
        item = item.toLowerCase();

        if ( lastCharCode === "z".charCodeAt( 0 ) ) {
            if ( allAreZ(item) ) {
                // console.log( "Reached the end, adding a letter");
                return Array(item.length +2).join("a");    
            } else { 
                var index = findIncrementIndex(item);
                var charCode = item.charCodeAt( index -1 );
                var newChar = String.fromCharCode( ++charCode );
                item = item.replace(/[a-y]z/, newChar + "a").replace(/z+$/, "a");
                // console.log( "Reached the end, next set is: " + item);
                return item;
            }

        } else {
            var newChar = String.fromCharCode( ++lastCharCode );
            // console.log( "Next Character is: " + newChar + " Code: " + lastCharCode + " Input: " + item);
            return item.replace( /\w$/, newChar );
        }
    }
  }
};
From a once over:


As a caller I would rather whether start or end was not a string instead of getting ERROR: start and end must both be Strings!
Indentation! Please consider using something like jsbeautifier
You can merge these

var range = [];
range.push(current); //Put the start directly into the range.


into

var range = [start]; //Begin with the start &lt;- Perhaps too zen a comment

Do not keep commented out code
I cannot understand why you would need 

while(!stringEqual(current.split(""), end.split(""))) {


why can't you simply

while(current != end) {

Also, this, I cant see when you would need this:

if ( typeof item === "number" ) {
    return item++;


Since you verify that both start and end are string, this should never happen?
allAreZ is written in a convoluted way, in this type of function ( small, and dedicated to 1 task), it is appropriate to return immediately. You could try something like 

function allZ( string ) {
    var i = 0;
    while ( i &lt; string.length ) {
        if ( string[i] !== "z" ) {
            return false; 
        }
        i++;
    }
    return true;
}


or, you something fun like this

function allZ( string ) {
    return string.split('z').length == string.length + 1;
}



I am mulling about writing something far shorter with .toString(26) To be sure zzzzzz equals 308915775, that is a lot of entries to store in array, in fact at this point it is silly to store this into an array. You would be better of writing an iterator class which provides a next() function for ranges in that size.



function charRange(start, end)
{
  if(typeof start !=  "string" ){
    throw 'start must be a string';
  }
  
  if(typeof end !=  "string" ){
    throw 'end must be a string';
  }

  var range = [],
      current,
      mapRadix = {},
      mapAlphabet = {},
      a = 'a'.charCodeAt(0);
  
  for( var i = 0 ; i &lt; 26 ; i++ ){
    mapRadix[i.toString(26)] = String.fromCharCode(a+i);
    mapAlphabet[String.fromCharCode(a+i)] = i.toString(26);
  }
  
  function string2Number( s ){
    var i26 = '';
    for( var i = 0 ; i &lt; s.length ; i++){
      i26 += mapAlphabet[ s[i] ];
    }
    return parseInt(i26,26);
  }
  
  function number2String( int ){
    var n = int.toString(26),
        s = '';
    for( var i = 0 ; i &lt; n.length ; i++){
      s += mapRadix[ n[i] ];
    }
    return s;
  }
  
  current = string2Number( start );
  end = string2Number( end ) + 1;
  if( current &gt; end ){
    throw 'start must be smaller than end';
  }
    
  while(current != end ) {
    range.push(number2String(current++));
  }
               
  return range;
}