13

This is probably an unusual request, but for my script I need a function that increments by letter instead of number. For example:

This is a numeric example:

var i = 0;
while(condition){
 window.write('We are at '+i);
 ++i;
}

Essentially, I want to count with letters, like Microsoft Excel does, instead of numbers. So instead of printing "We are at 0", "We are at 1", "We are at 2", etc., I need to print "We are at A", "We are at B", "We are at C", etc.

To mimic Excel (the only example I can think of), after reaching index 25 (Z), we could move on to 'AA', 'AB', 'AC', etc.

So it would work great like so:

var i = 0;
while(condition){
 window.write('We are at '+toLetter(i));
 ++i;
}

Even better if somebody can write a function that then converts a letter back into a digit, i.e. toNumber('A') = 0 or toNumber('DC') = 107 (I think).

Thanks!

M Miller
  • 5,364
  • 9
  • 43
  • 65
  • 2
    Sorry for asking, but what did you try? So far it looks like a homework to me. – alf Jun 18 '12 at 19:09
  • So you need to write toNumber() and toLetter(). This looks like a very simple algorithmic quest. Show us what you tried. – Al Kepp Jun 18 '12 at 19:10
  • You could build an array of letters, and then compare your count to the key in the array (making sure to compensate for the "0" position). If your count starts at zero, then you're good. – gtr1971 Jun 18 '12 at 19:12
  • I found a solution by thinking in terms of base 26. http://frugalcoder.us/post/2011/02/24/Convert-an-integer-to-a-base26-alpha-string.aspx – M Miller Jun 18 '12 at 19:20
  • That code is pretty terrible. It converts the number to a string, and then goes back and fixes it. It'd be better (and easier) to just convert it directly. – Pointy Jun 18 '12 at 19:22
  • This is not homework. I am using a number-based system to assign unique ID's and a letter-based system for temporary ID's before they get assigned permanent ones in the database. I suppose, alternatively, I could simply prefix them with a letter, i.e. t0, t1, t2, .... – M Miller Jun 18 '12 at 19:40
  • Homework: what part of your code would result in *TypeError: Object [object Window] has no method 'write'* – KooiInc Jun 18 '12 at 20:04
  • Please don't be patronizing; write is not a method of the window object. I do not traditionally use such functions and I slipped. Almost all of my JavaScript now implements the use of jQuery and writes values to elements. – M Miller Jun 19 '12 at 20:24

7 Answers7

40

Here's a simple recursive function to convert the numbers to letters.

It's one-based, so 1 is A, 26 is Z, 27 is AA.

function toLetters(num) {
    "use strict";
    var mod = num % 26,
        pow = num / 26 | 0,
        out = mod ? String.fromCharCode(64 + mod) : (--pow, 'Z');
    return pow ? toLetters(pow) + out : out;
}

Here's a matching function to convert the strings back to numbers:

function fromLetters(str) {
    "use strict";
    var out = 0, len = str.length, pos = len;
    while (--pos > -1) {
        out += (str.charCodeAt(pos) - 64) * Math.pow(26, len - 1 - pos);
    }
    return out;
}

A test: http://jsfiddle.net/St6c9/

Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
3

Something like this you mean?

function num2chars(num, upper){
 num2chars.letters = num2chars.letters || 'abcdefghijklmnopqrstuvwxyz'.split('');
 var ret = repeat(num2chars.letters[num%26],Math.floor(num/26));

 function repeat(chr,n){
  if (n<1) {return chr;}
  return new Array(n+1).join(chr);
 }

 return upper ? ret.toUpperCase() : ret;
}
//usage
while(i<104){
 console.log(num2chars((i+=1),true));
}
//=> A..Z, AA..ZZ, AAA..ZZZ
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • JavaScript lets you index into strings as if they were arrays, so there's no need to `.split()` really. – Pointy Jun 18 '12 at 19:24
  • @Pointy: Moved my comment here since it's more relevant. The `.split()` is needed for the sake of IE *(8 and below I think)*. Otherwise you'd need `.charAt()`. –  Jun 18 '12 at 19:33
  • 2
    Oh, really? Hmm ... I should make sure I haven't coded myself any IE8 bugs lately :-) – Pointy Jun 18 '12 at 19:40
0

Create an array of letters A, B, C, D, etc. then call A by using array[0] since 0 is the index of A you can use array[i] as the index, just validate so i can't be over 25.

Use either of these ways to create the array:

var alphabet = new Array("A","B","C");

var alphabet = new Array(25);
alphabet[0] = "A";
alphabet[1] = "B";
alphabet[2] = "C";

instead of toLetter(i); use alphabet[i];

erran
  • 1,300
  • 2
  • 15
  • 36
  • I don't think I'd do it this way, but if I did I'd just make a string with all the characters of the alphabet in it. JavaScript lets you access the characters of a string with array notation. Also: there's no need to pre-allocate space in an array via the Array constructor; it won't actually do anything in any modern runtime. – Pointy Jun 18 '12 at 19:20
0

Try the following. Tried and tested in few minutes

 var prefix = Array('','A','B'); //this will extends to 3x26 letters. Determines the Max generated
//first element of prefix is `''` so you can have A B C D
var prefix = Array('','A','B');
var alphabets = Array('A','B','C','D'); //extend this to Z
var letters = Array();

function fillArray()
{
   var prefix_len = prefix.length;
   var array_len = prefix_len * alphabets.length;
   var alpha_len = alphabets.length;

   for(var i=0; i<prefix_len; i++)
   {
      for(var a=0; a<alpha_len; a++)
         letters.push(''+prefix[i]+alphabets[a]);
   }



}

function getLetter(index)
{
  return letters[index];
}


function generateTestValues() 
{
  fillArray();
  //make sure 10 is less than letters.length
  for(var i=0; i<10; i++)
     document.write(getLetter(i)+' ');  //A B C D AA AB AC AD BA BB BC....
}

HTML

<span id="clickable" onclick="generateTestValues()">Click Me</span>
codingbiz
  • 26,179
  • 8
  • 59
  • 96
0

Thats how you can generate random letters:

function getRandomArbitrary(min, max) {
  max = Math.ceil(max);
  min = Math.floor(min); 
  return Math.round(Math.random() * (max - min) + min);
}

function assignLetter(){
  var group = ['A', 'B', 'C', 'D'];
  var text = 'We are at ';
  var str = '';
  str = text + group[getRandomArbitrary(0, group.length-1)];
  return str;
}
assignLetter();
Bekzat
  • 170
  • 1
  • 6
0

For future readers I leave what I think is a more straightforward solution:

    const aLetterCode = 97
    const getLetterFromId = (number) => String.fromCharCode(aLetterCode + number)

    console.log('code 0 ->', getLetterFromId(0)) // a
    console.log('code 1 ->', getLetterFromId(1)) // b
    console.log('code 12 ->', getLetterFromId(12)) // m
Lianel
  • 101
  • 10
0

Try the following:

function getCharCode(value) {
  if (value===null || value === undefined) return "";
  if (value < 26) return String.fromCharCode(65 + value);
  return (
    getCharCode(Number(value / 26) - 1) + String.fromCharCode(65 + (value % 26))
  );
}
Rohit Rahman
  • 1,054
  • 1
  • 7
  • 13