Python 生成A1引用样式列名的最惯用方法是什么?

Python 生成A1引用样式列名的最惯用方法是什么?,python,string,dictionary,spreadsheet,idioms,Python,String,Dictionary,Spreadsheet,Idioms,我试图创建一个算法,隐式地处理每个可能的单元标识符;使用A1参考样式。A1引用样式通常限于列(A-IV)和行(0-65536)。这是用于生成Excel和数字电子表格的格式。我理解这些限制的原因,但我试图用“正确”的方式来命名这些列;程序上。更具体地说,我试图理解如何按程序为每一列生成正确的名称。结果将是一个包含a-Z列、AA-ZZ列、AAA-ZZZ列等的字典。此“电子表格”的单元格类似于AHD129、A1或XAPRC100204 这一切都是从尝试生成棋盘的单元格开始的,这相对容易: board

我试图创建一个算法,隐式地处理每个可能的单元标识符;使用A1参考样式。A1引用样式通常限于列(A-IV)和行(0-65536)。这是用于生成Excel和数字电子表格的格式。我理解这些限制的原因,但我试图用“正确”的方式来命名这些列;程序上。更具体地说,我试图理解如何按程序为每一列生成正确的名称。结果将是一个包含a-Z列、AA-ZZ列、AAA-ZZZ列等的字典。此“电子表格”的单元格类似于AHD129、A1或XAPRC100204

这一切都是从尝试生成棋盘的单元格开始的,这相对容易:

board = {}
for file in 'ABCDEFGH':
    for rank in range(0, 8):
        cell = file + str(rank + 1)
        board[cell] = ''
这将处理棋盘(A1-H8)的每个组合,并将其全部放入字典中。问题是它非常明确

我们可以隐式地处理每个可能的组合(A1-Z26),就像这样

def generate(units):
    cells = {}
    alphabet = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    for column in range(0, units):
        char = alphabet[column]
        for row in range(0, units):
            cell = char + str(row + 1)
            cells[cell] = ''
    return cells
这更好,因为它允许我们在给定范围(A1-Z26)内生成“棋盘”。您可以将1到26之间的任意整数传递给此函数,但当(单位>26)时将引发错误。 如果我们将“棋盘”除以27个单位,那么我们需要生成(A1-AA27)

单位=1->26 |结果A1-Z26

单位=1->52 |结果A1-AZ52

单位=1->78 |结果A1-BZ78

单位=1->104 |结果A1-CZ104

我的数学可能会偏离几个整数,但我基本上只是尝试创建一个正方形的表示。列和行总是相等的,这就是为什么我使用嵌套for循环来处理这个问题。我知道我可以编写一个大规模的条件块来处理26个字符以外的每个范围,比如:

if column in range(0, len(alphabet)):
    char = alphabet[i]
elif column in range(len(alphabet), len(alphabet) * 2):
    char = 'A' + alphabet[i]
elif column in range(len(alphabet) * 2, len(alphabet) * 3):
    char = 'B' + alphabet[i]
…但这是违反直觉的。我试图处理任意整数(例如:1000000或63432)。我假设(welp)它与通过while循环“暴力强制”列名有关,但我也知道这是Python。i、 有一个非常简单的方法来解决这个问题,我以前从未遇到过

我不想让任何人为我“编写代码”,但有人能为我指出正确的方向吗?如何以A1引用样式电子表格格式按程序生成列名?从Python中给定的字符列表构造字符串的最佳方法是什么

请不要建议使用库来解决这个问题,因为我正试图理解底层解决方案。对于任何不正确的术语,我深表歉意,如果我用错了什么,请纠正我的话。任何帮助或考虑都将不胜感激。我非常愿意为未来的观众修改整个问题。

这种编码称为双射基26。或者,您也可以在上面的堆栈溢出帖子中使用base26的奇特术语。实际上,解码真的很容易。ABC=1*26*26+2*26+3。将数字视为基数26,但A=1,Z=26,而不是A=0,Z=25

==更新==

现在我想起来了,相反的方向也很容易。转换为基数26的标准算法是重复除以26,余数的数字顺序相反

#convert 65536 
divmod(65535, 26)
(2520, 15)
>>> divmod(2519, 26)
divmod(2519, 26)
(96, 23)
>>> divmod(95, 26)
divmod(95, 26)
(3, 17)
>>> divmod(2, 16)
divmod(2, 16)
(0, 2)
# The remainders in reverse order are 2,17,23,15 -> CRXP
对于此算法,重复将之前的商减去1除以26。当0-25转换为A-Z时,余数按相反顺序给出答案

#convert 65536 
divmod(65535, 26)
(2520, 15)
>>> divmod(2519, 26)
divmod(2519, 26)
(96, 23)
>>> divmod(95, 26)
divmod(95, 26)
(3, 17)
>>> divmod(2, 16)
divmod(2, 16)
(0, 2)
# The remainders in reverse order are 2,17,23,15 -> CRXP

我回来了;怀着复仇的心情。我找不到最惯用的方法来实现这一点,但我确实提出了一种生成A1引用样式网格的简单方法。可以为宽度或高度参数输入任何大于零的整数

def generate_cells(width, height):
    """Generates cell-names for an 'A1 Reference Style' grid,
        and places them into a dictionary with empty values.
    width and height parameters are both = integer > zero"""
    
    alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' # explicit to avoid import
    empty_grid = {}
    for column in range(1, width+1):
    
        bijective_hexavigesimal = []
        while column: # repetitiously reduce unit with divmod()
            column, remainder = divmod(column - 1, 26)
            bijective_hexavigesimal[:0] = alphabet[remainder]
            
        column = ''.join(bijective_hexavigesimal)
        
        for row in range(1, height+1):
            cell = column + str(row)
            empty_grid[cell] = ''
                 
    return empty_grid

返回具有空字符串值的键字典。。。享受。

看看我的答案。这正是我想要的,但恰恰相反。这是搜索,而我试图“生成”。尽管如此,这确实为我指明了正确的方向。我将尝试修改你的代码,使其更小,然后将其发布在这里供未来的观众观看。谢谢你,马蒂诺!双射六面体。。。我知道这是一件事,我只是不知道什么哈哈谢谢你给我指出了正确的方向,这个术语非常有用!!