196

I want to convert an integer into its character equivalent based on the alphabet. For example:

0 => a
1 => b
2 => c
3 => d

etc. I could build an array and just look it up when I need it but I’m wondering if there’s a built in function to do this for me. All the examples I’ve found via Google are working with ASCII values and not a character’s position in the alphabet.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
VIVA LA NWO
  • 3,852
  • 6
  • 24
  • 21

12 Answers12

357

Assuming you want lower case letters:

var chr = String.fromCharCode(97 + n); // where n is 0, 1, 2 ...

97 is the ASCII code for lower case 'a'. If you want uppercase letters, replace 97 with 65 (uppercase 'A'). Note that if n > 25, you will get out of the range of letters.

Daniel Vandersluis
  • 91,582
  • 23
  • 169
  • 153
88

Will be more portable in case of extending to other alphabets:

char='abcdefghijklmnopqrstuvwxyz'[code]

or, to be more compatible (with our beloved IE):

char='abcdefghijklmnopqrstuvwxyz'.charAt(code);
mbq
  • 18,510
  • 6
  • 49
  • 72
  • 6
    Much more elegant than `String.fromCharCode` in my opinion, as as you said, it extends very easily. – Sasha Chedygov Jun 29 '10 at 22:01
  • 8
    And when you have no need of extending, maybe more prone to errors? abcede – Nelson Rothermel Jun 29 '10 at 22:07
  • And it will give `undefined` in case of bad code, which is more sensible that some weird white rectangles. – mbq Jun 29 '10 at 22:08
  • 5
    FYI JScript (IE) does not support the index operator `[]` on strings. – Crescent Fresh Jun 29 '10 at 22:21
  • 4
    @Crescent, the `[]` property accessor on strings is supported on IE from IE8 up (IE8 in IE7 compat mode also doesn't works), [`String.prototype.chatAt`](http://bclary.com/2004/11/07/#a-15.5.4.4) is preferred instead of `[]` for browser compatibility. E.g. `'foo'.charAt(0) == 'f'` – Christian C. Salvadó Jun 29 '10 at 22:53
  • 2
    @Crescent, forgot to mention that the `[]` property accessor on strings is standardized on ECMAScript 5 (see [\[\[GetOwnProperty\]\](P)](http://ecma262-5.com/ELS5_Section_15.htm#Section_15.5.5.2)). – Christian C. Salvadó Jun 29 '10 at 23:01
  • @Crescent, @CMS, thanks for your comments, I have upgraded the answer to reflect them. – mbq Jun 30 '10 at 18:57
  • I agree with the char='abcdefghijklmnopqrstuvwxyz'.charAt(code); version, this is IMO the cleanest way. – Oldenborg Aug 07 '14 at 08:35
  • I love this approach, and if you want to add more characters, you can do so, without getting into the complication of finding the ASCII code. For example the char ñ '...mnñop...' for the Spanish alphabet. – Jaider Aug 10 '16 at 18:21
34

If you don't mind getting multi-character strings back, you can support arbitrary positive indices:

function idOf(i) {
  return (
    (i >= 26 ? idOf(((i / 26) >> 0) - 1) : "") +
    "abcdefghijklmnopqrstuvwxyz"[i % 26 >> 0]
  );
}

[0, 1, 25, 26, 27, 701, 702, 703].map(idOf);
// ['a', 'b', 'z', 'aa', 'ab', 'zz', 'aaa', 'aab']

(Not thoroughly tested for precision errors :)

z0r
  • 8,185
  • 4
  • 64
  • 83
  • 1
    Recursive function, very nice! – John Virgolino Mar 22 '16 at 22:24
  • @mikemaccana, why this edit? I think it makes it harder to read. Now I have to scroll horizontally to read the code. – z0r May 11 '17 at 01:23
  • @z0r So people using the code won't have to fix the newline. There's no reason to break lines arbitrarily, editors will wrap at the character size of their window. – mikemaccana May 12 '17 at 13:42
  • 1
    Nice idea, but it didn't work until changed into this :```function idOf(i) { return (i >= 26 ? idOf(Math.floor(i / 26) -1 ) : '') + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[i % 26]; } ``` – PatrickvL Apr 14 '20 at 15:02
  • exactly what I was looking or – jones Sep 02 '21 at 05:53
20

A simple answer would be (26 characters):

String.fromCharCode(97+n);

If space is precious you could do the following (20 characters):

(10+n).toString(36);

Think about what you could do with all those extra bytes!

How this works is you convert the number to base 36, so you have the following characters:

0123456789abcdefghijklmnopqrstuvwxyz
^         ^
n        n+10

By offsetting by 10 the characters start at a instead of 0.

Not entirely sure about how fast running the two different examples client-side would compare though.

Dan
  • 501
  • 4
  • 8
9

I don't like all the solutions that use magic numbers like 97 or 36.

const A = 'A'.charCodeAt(0);

let numberToCharacter = number => String.fromCharCode(A + number);

let characterToNumber = character => character.charCodeAt(0) - A;

this assumes uppercase letters and starts 'A' at 0.

junvar
  • 11,151
  • 2
  • 30
  • 46
6

Javascript's String.fromCharCode(code1, code2, ..., codeN) takes an infinite number of arguments and returns a string of letters whose corresponding ASCII values are code1, code2, ... codeN. Since 97 is 'a' in ASCII, we can adjust for your indexing by adding 97 to your index.

function indexToChar(i) {
  return String.fromCharCode(i+97); //97 in ASCII is 'a', so i=0 returns 'a', 
                                    // i=1 returns 'b', etc
}
hundredwatt
  • 308
  • 1
  • 8
4

There you go: (a-zA-Z)

function codeToChar( number ) {
  if ( number >= 0 && number <= 25 ) // a-z
    number = number + 97;
  else if ( number >= 26 && number <= 51 ) // A-Z
    number = number + (65-26);
  else
    return false; // range error
  return String.fromCharCode( number );
}

input: 0-51, or it will return false (range error);

OR:

var codeToChar = function() {
  var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
  return function( code ) {
    return abc[code];
  };
})();

returns undefined in case of range error. NOTE: the array will be created only once and because of closure it will be available for the the new codeToChar function. I guess it's even faster then the first method (it's just a lookup basically).

gblazex
  • 49,155
  • 12
  • 98
  • 91
4

Use String.fromCharCode. This returns a string from a Unicode value, which matches the first 128 characters of ASCII.

var a = String.fromCharCode(97);
James Westgate
  • 11,306
  • 8
  • 61
  • 68
1

The only problem with @mikemaccana's great solution is that it uses the binary >> operator which is costly, performance-wise. I suggest this modification to his great work as a slight improvement that your colleagues can perhaps read more easily.

const getColumnName = (i) => {
     const previousLetters = (i >= 26 ? getColumnName(Math.floor(i / 26) -1 ) : '');
     const lastLetter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[i % 26]; 
     return previousLetters + lastLetter;
}

Or as a one-liner

const getColumnName = i => (i >= 26 ? getColumnName(Math.floor(i / 26) -1 ) : '') + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[i % 26];

Example:

getColumnName(0); // "A"
getColumnName(1); // "B"
getColumnName(25); // "Z"
getColumnName(26); // "AA"
getColumnName(27); // "AB"
getColumnName(80085) // "DNLF"
Pang
  • 9,564
  • 146
  • 81
  • 122
Pandem1c
  • 778
  • 1
  • 5
  • 12
1

Try

(n+10).toString(36)

chr = n=>(n+10).toString(36);

for(i=0; i<26; i++) console.log(`${i} => ${ chr(i) }`);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
0

If you are looking for TypeScript working functions then follow

public numericValue = (alphaChar: any) => alphaChar.toUpperCase().charCodeAt(0) - 64;

public alphaValue = (numericDigit: any) => 
   String.fromCharCode(64 + numericDigit) : '';

You can make several checks like (numericDigit >= 1 && numericDigit <= 26) ? inside function body as per the requirements.

Kapil Raghuwanshi
  • 867
  • 1
  • 13
  • 22
-3

Assuming you want uppercase case letters:

function numberToLetter(num){
        var alf={
            '0': 'A', '1': 'B', '2': 'C', '3': 'D', '4': 'E', '5': 'F', '6': 'G'
        };
        if(num.length== 1) return alf[num] || ' ';
        return num.split('').map(numberToLetter);
    }

Example:

numberToLetter('023') is ["A", "C", "D"]

numberToLetter('5') is "F"

number to letter function

Rafael Corrêa Gomes
  • 1,751
  • 1
  • 22
  • 31