I have a working code (below) to convert a number
to Excel-like (A...Z AA...AZ BA...BZ ...ZA-ZZ
) column codes (headers).
For simplicity I limited it to 1 or 2 character codes.
Can the algorithm be streamlined by using a bit more of elementary math or using it differently?
Please note that I just happened to need it in JavaScript (so I wrote it in JS) and am not looking for pure code improvements.
function numberToLetters(nNum) {
var result;
if (nNum <= 26) {
result = letter(nNum);
} else {
var modulo = nNum % 26;
var quotient = Math.floor(nNum / 26);
if (modulo === 0) {
result = letter(quotient - 1) + letter(26);
} else {
result = letter(quotient) + letter(modulo);
}
}
return result;
}
function letter(nNum) {
var a = "A".charCodeAt(0);
return String.fromCharCode(a + nNum - 1);
}
-
1\$\begingroup\$ Why not create a 676 (26^2) element lookup array? That could be bad if you extend to 3 or more characters, but for 1 or 2 it would work. \$\endgroup\$Dan Pichelman– Dan Pichelman2014年12月09日 20:15:10 +00:00Commented Dec 9, 2014 at 20:15
-
\$\begingroup\$ It seems that Implement numbering scheme like A,B,C... AA,AB,... AAA..., similar to converting a number to radix26 has the type of answer I was looking for. \$\endgroup\$PM 77-1– PM 77-12014年12月11日 01:00:00 +00:00Commented Dec 11, 2014 at 1:00
-
2\$\begingroup\$ This question has been mentioned on meta. \$\endgroup\$RubberDuck– RubberDuck2014年12月14日 11:17:32 +00:00Commented Dec 14, 2014 at 11:17
2 Answers 2
It depends what do you mean by "streamlined"? There is not much you can do to, for example, reduce the complexity of your algorithm. What you can do is to increase the clarity of your algorithm, which falls into the domain of code review or improvement.
Maybe there is some math trick that can do the job faster, or with fewer lines of code. However there is also a good chance that such a trick will not make your algorithm look more "streamlined". It might even go the opposite direction and make it harder for the code to reveal its intention.
That being said, the problem you solved can be generalized to the problem of converting number to an arbitrary base, and then encode the number-in-new-base using a set of arbitrary symbols. In your case, the base is 26. The symbols are ["A", "B", ..., "Z"]. How a number is encoded or represented in a new base is independent of the base-convertion itself.
Looking at it this way, the only improvement I can think of is "do not limit the convertion to only one or two characters". Such a constraint does not bring much simplicity. But this probably is still implementation level improvement.
Your algorithm (or api) could eventually look like: number.convertToBase(26).encodeIn (["A", "B", ... , "Z"]). Is this more "streamlined"?
-
\$\begingroup\$ I already pointed (linked) to the answer I liked (both in my comments and in the closing reason). Look at Linked section on the right. You are wrong about the math part. It's
base 27
that needs to be used and then properly shifted. Edge cases are "Z", "AA", "AZ". \$\endgroup\$PM 77-1– PM 77-12014年12月20日 00:58:43 +00:00Commented Dec 20, 2014 at 0:58
I don't really see, where you could apply major improvements. You certainly could remove the magic number 26
from your code and rename you letter
-function. Furthermore, it is not neccessary to compute the character code of the letter A
of every call to letter
. Your calculation can be marginally simplified as well.
var charCodeOfA = "A".charCodeAt(0),
alphabetLength = "Z".charCodeAt(0) - charCodeOfA + 1;
function numberToLetters(nNum) {
if (nNum <= alphabetLength) {
return convertNumberToLetter(nNum);
} else {
var firstNumber = Math.floor((nNum - 1) / alphabetLength);
var firstLetter = convertNumberToLetter(firstNumber);
var secondNumber = (nNum % alphabetLength) || alphabetLength;
var secondLetter = convertNumberToLetter(secondNumber);
return firstLetter + secondLetter;
}
}
function convertNumberToLetter(nNum) {
var charCode = charCodeOfA + nNum - 1;
return String.fromCharCode(charCode);
}
Explore related questions
See similar questions with these tags.