获取 Excel 列标签(A、B、...、Z、AA、...、AZ、BA、...、ZZ、AAA、AAB、...)
Get the Excel column label (A, B, ..., Z, AA, ..., AZ, BA, ..., ZZ, AAA, AAB, ...)
给定 Excel 列的字母 header 我需要输出列号。
它是 A-Z
,然后是 AA-AZ
然后是 BA-BZ
等等。
我想像以 26 为底数一样通过它,我只是不知道如何实现它。
它适用于像 AA
这样的简单的,因为 26^0 = 1
+ 26^1 = 26
= 27
.
但是对于 ZA
这样的东西,如果我这样做 26 ^ 26
(z 是第 26 个字母),输出显然太大了。我错过了什么?
如果我们将“A”解码为 0,“B”解码为 1,...那么“Z”为 25,“AA”为 26。
所以它不是纯 26 基编码,因为前缀“A”对值没有影响,“AAAB”必须与“B”相同,就像在十进制0001等于1。但是这里不是这样。
“AA”的值为1*261 + 0,“ZA”的值为26*261 + 0 .
我们可以概括地说,“A”的值应为 1,“B”的值应为 2,...等(单个字母编码除外)。所以在“AAA”中,最右边的“A”代表系数为0,而其他的“A”代表系数:1*262 + 1*261 + 0
这导致以下代码:
def decode(code):
val = 0
for ch in code: # base-26 decoding "plus 1"
val = val * 26 + ord(ch) - ord("A") + 1
return val - 1
当然,如果我们希望列号以 1 而不是 0 开头,那么只需将最后的语句替换为:
return val
幂和
你可以求出 26 的幂的倍数:
def xl2int(s):
s = s.strip().upper()
return sum((ord(c)-ord('A')+1)*26**i
for i,c in enumerate(reversed(s)))
xl2int('A')
# 1
xl2int('Z')
# 26
xl2int('AA')
# 27
xl2int('ZZ')
# 702
xl2int('AAA')
# 703
int
内置
您可以使用带有 base
参数的字符串翻译 table 和 int
内置函数。
因为你有一个破损的基础,你需要为长度为 n 的输入添加 26**n+26**(n-1)+...+26**0,你可以用 int('11...1', base=26)
其中 1 的个数与输入字符串的长度一样多。
from string import ascii_uppercase, digits
t = str.maketrans(dict(zip(ascii_uppercase, digits+ascii_uppercase)))
def xl2int(s):
s = s.strip().upper().translate(t)
return int(s, base=26)+int('1'*len(s), base=26)
xl2int('A')
# 1
xl2int('Z')
# 26
xl2int('AA')
# 27
xl2int('ZZ')
# 702
xl2int('AAA')
# 703
翻译的工作原理
它移动每个字符,使 A -> 0,B -> 1...J -> 9,K -> A...Z -> P。然后使用 [=12 将其转换为整数=].然而,获得的数字是不正确的,因为我们缺少数字中每个数字位置的 26**x,因此我们添加与输入中的数字一样多的 26 次方。
给定 Excel 列的字母 header 我需要输出列号。
它是 A-Z
,然后是 AA-AZ
然后是 BA-BZ
等等。
我想像以 26 为底数一样通过它,我只是不知道如何实现它。
它适用于像 AA
这样的简单的,因为 26^0 = 1
+ 26^1 = 26
= 27
.
但是对于 ZA
这样的东西,如果我这样做 26 ^ 26
(z 是第 26 个字母),输出显然太大了。我错过了什么?
如果我们将“A”解码为 0,“B”解码为 1,...那么“Z”为 25,“AA”为 26。
所以它不是纯 26 基编码,因为前缀“A”对值没有影响,“AAAB”必须与“B”相同,就像在十进制0001等于1。但是这里不是这样。
“AA”的值为1*261 + 0,“ZA”的值为26*261 + 0 .
我们可以概括地说,“A”的值应为 1,“B”的值应为 2,...等(单个字母编码除外)。所以在“AAA”中,最右边的“A”代表系数为0,而其他的“A”代表系数:1*262 + 1*261 + 0
这导致以下代码:
def decode(code):
val = 0
for ch in code: # base-26 decoding "plus 1"
val = val * 26 + ord(ch) - ord("A") + 1
return val - 1
当然,如果我们希望列号以 1 而不是 0 开头,那么只需将最后的语句替换为:
return val
幂和
你可以求出 26 的幂的倍数:
def xl2int(s):
s = s.strip().upper()
return sum((ord(c)-ord('A')+1)*26**i
for i,c in enumerate(reversed(s)))
xl2int('A')
# 1
xl2int('Z')
# 26
xl2int('AA')
# 27
xl2int('ZZ')
# 702
xl2int('AAA')
# 703
int
内置
您可以使用带有 base
参数的字符串翻译 table 和 int
内置函数。
因为你有一个破损的基础,你需要为长度为 n 的输入添加 26**n+26**(n-1)+...+26**0,你可以用 int('11...1', base=26)
其中 1 的个数与输入字符串的长度一样多。
from string import ascii_uppercase, digits
t = str.maketrans(dict(zip(ascii_uppercase, digits+ascii_uppercase)))
def xl2int(s):
s = s.strip().upper().translate(t)
return int(s, base=26)+int('1'*len(s), base=26)
xl2int('A')
# 1
xl2int('Z')
# 26
xl2int('AA')
# 27
xl2int('ZZ')
# 702
xl2int('AAA')
# 703
翻译的工作原理
它移动每个字符,使 A -> 0,B -> 1...J -> 9,K -> A...Z -> P。然后使用 [=12 将其转换为整数=].然而,获得的数字是不正确的,因为我们缺少数字中每个数字位置的 26**x,因此我们添加与输入中的数字一样多的 26 次方。