javascript 将数字转换为26个字符以外的字母

dzjeubhm  于 2023-01-08  发布在  Java
关注(0)|答案(8)|浏览(124)

我正在为一个可Map的电子表格导出功能创建一些客户端函数。
我使用jQuery来管理列的排序顺序,但每列的排序方式都类似于Excel电子表格,即a b c d e......x y z aa ab ac ad等
我怎样才能把一个数字生成为一个字母?我应该定义一个固定的值数组吗?还是有一个动态的方法来生成它?

uz75evzq

uz75evzq1#

我觉得你在找这样的东西

function colName(n) {
        var ordA = 'a'.charCodeAt(0);
        var ordZ = 'z'.charCodeAt(0);
        var len = ordZ - ordA + 1;
      
        var s = "";
        while(n >= 0) {
            s = String.fromCharCode(n % len + ordA) + s;
            n = Math.floor(n / len) - 1;
        }
        return s;
    }

// Example:

    for(n = 0; n < 125; n++)
            document.write(n + ":" + colName(n) + "<br>");
k2fxgqgv

k2fxgqgv2#

这是一个非常简单的方法:

function numberToLetters(num) {
    let letters = ''
    while (num >= 0) {
        letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[num % 26] + letters
        num = Math.floor(num / 26) - 1
    }
    return letters
}
p5fdfcr1

p5fdfcr13#

function getColumnDescription(i) {
  const m = i % 26;
  const c = String.fromCharCode(65 + m);
  const r = i - m;
  return r > 0
    ? `${getColumnDescription((r - 1) / 26)}${c}`
    : `Column ${c}`
}

用法:

getColumnDescription(15)
"Column P"

getColumnDescription(26)
"Column AA"

getColumnDescription(4460)
"Column FOO"
ruarlubt

ruarlubt4#

如果您将数据放在二维数组中,例如

var data = [
  ['Day', 'score],
  ['Monday', 99],
];

您可以将行/列Map到电子表格单元格编号,如下所示(基于上面的代码示例):

function getSpreadSheetCellNumber(row, column) {
  let result = '';

  // Get spreadsheet column letter
  let n = column;
  while (n >= 0) {
    result = String.fromCharCode(n % 26 + 65) + result;
    n = Math.floor(n / 26) - 1;
  }

  // Get spreadsheet row number
  result += `${row + 1}`;

  return result;
};

例如,数据[0][0]中的“天”值将进入电子表格单元格A1。

> getSpreadSheetCellNumber(0, 0)
> "A1"

这也适用于超过26列的情况:

> getSpreadSheetCellNumber(0, 26)
> "AA1"
jutyujz0

jutyujz05#

假设numbers中包含列的编号,可以使用如下代码,因此在这段代码之后,您将获得列的字符串名称:

var letters = ['a', 'b', 'c', ..., 'z'];
var numbers = [1, 2, 3, ...];
var columnNames = [];
for(var i=0;i<numbers.length;i++) {
    var firstLetter = parseInt(i/letters.length) == 0 ? '' : letters[parseInt(i/letters.length)];
    var secondLetter = letters[i%letters.length-1];
    columnNames.push(firstLetter + secondLetter);
}
14ifxucb

14ifxucb6#

简单递归解:

function numberToColumn(n) {
  const res = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[n % 26];
  return n >= 26 ? numberToColumn(Math.floor(n / 26) - 1) + res : res;
}
ncgqoxb0

ncgqoxb07#

下面是一个依赖于.toString(26)的替代方法,它使用到base-26的转换,然后转换字符,使它们在a..z范围内:

const conv = ((base, alpha) => { // Closure for preparing the function
    const map = Object.fromEntries(Array.from(alpha, (c, i) => [c, alpha[i + 10]]));
    return n => (n + base).toString(26).replace(/o*p/, "").replace(/./g, m => map[m]);
})(parseInt("ooooooooop0", 26), "0123456789abcdefghijklmnopqrstuvwxyz");

// Example:
for (let n = 0; n < 29; n++) console.log(n, conv(n));
console.log("...");
for (let n = 690; n < 705; n++) console.log(n, conv(n));

∮ ∮关于神奇的数字∮
神奇值“ooooooooop 0”的推导如下:

  • 它是一个以基数26表示的数字,以标准的方式,即其中十个数字也起作用,然后是字母表的第一个字母。
  • 基数26中最大的“数字”是“p”(拉丁字母表中的第16个字母),“o”是第二大的数字。
  • 魔法值是由一个足够长的序列组成的,序列中有一个但最大的数字,然后是最大的数字,最后是一个0。
  • 由于JavaScript整数在Number.MAX_SAFE_INTEGER附近达到最大值(更大的整数会出现舍入误差),因此不需要比所选的更长的“o”序列。我们可以看到Number.MAX_SAFE_INTEGER.toString(26)有12位,因此可以确保精度达到11位(基数为26),这意味着我们需要9个“o”。
  • 这个神奇的数字确保了如果我们把单位加进去(在基数26中),我们将总是具有以一系列“o”然后“p”开始的表示。这是因为在某个点最后一个数字将再次绕回0,并且“p”也将绕回0,把前面的“o”带到“p”。所以我们有这个不变量,数字总是从零或更多的“o”开始,然后是“p”。

更通用

上面的幻数可以通过代码推导出来,我们可以通过提供目标字母表使它更通用,目标字母表的长度也直接决定了基数(即字符串中的字符数)。
下面是与上面生成的相同的输出,但使用了更通用的函数:

function createConverter(targetDigits) {
    const radix = targetDigits.length,
          alpha = "0123456789abcdefghijklmnopqrstuvwxyz",
          map = Object.fromEntries(Array.from(alpha, 
                (src, i) => [src, targetDigits[i]]
          )), 
          base = parseInt((alpha[radix-1]+'0').padStart(
               Number.MAX_SAFE_INTEGER.toString(radix).length - 1, alpha[radix-2]
          ), radix),
          trimmer = RegExp("^" + alpha[radix-2] + "*" + alpha[radix-1]);
    return n => (n + base).toString(radix)
                          .replace(trimmer, "")
                          .replace(/./g, m => map[m]);
}

// Example:
const conv = createConverter("abcdefghijklmnopqrstuvwxyz");
for (let n = 0; n < 29; n++) console.log(n, conv(n));
console.log("...");
for (let n = 690; n < 705; n++) console.log(n, conv(n));

这现在可以容易地适用于使用更简化的目标字母表(例如没有字母“l”和“o”),给出基数24而不是26:

function createConverter(targetDigits) {
    const radix = targetDigits.length,
          alpha = "0123456789abcdefghijklmnopqrstuvwxyz",
          map = Object.fromEntries(Array.from(alpha, 
                (src, i) => [src, targetDigits[i]]
          )), 
          base = parseInt((alpha[radix-1]+'0').padStart(
               Number.MAX_SAFE_INTEGER.toString(radix).length - 1, alpha[radix-2]
          ), radix),
          trimmer = RegExp("^" + alpha[radix-2] + "*" + alpha[radix-1]);
    return n => (n + base).toString(radix)
                          .replace(trimmer, "")
                          .replace(/./g, m => map[m]);
}

// Example without "l" and "o" in target alphabet:
const conv = createConverter("abcdefghijkmnpqrstuvwxyz");
for (let n = 0; n < 29; n++) console.log(n, conv(n));
console.log("...");
for (let n = 690; n < 705; n++) console.log(n, conv(n));
nxowjjhe

nxowjjhe8#

这涵盖了从1到1000的范围。超过这一点我还没有检查。

function colToletters(num) {
  let a = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  if (num < 27) return a[num % a.length];
  if (num > 26) {
    num--;
    let letters = ''
    while (num >= 0) {
      letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[num % 26] + letters
      num = Math.floor(num / 26) - 1
    }
    return letters;
  }
}

我可能错了,但是我检查了这个答案中的其他函数,它们似乎在26处失效,应该是Z,记住字母表中有26个字母,而不是25个。

相关问题