如何创建一个无限迭代器来生成一个递增的字母表模式?

How to create an infinite iterator to generate an incrementing alphabet pattern?

我创建了一个生成连续递增的字母列表的函数。 A,B,C ...,Z。在 Z 之后,它转到 AA,AB,AC ...AZ。这种模式重复。这类似于 MS Excel 的列名。目前,此函数生成一个有限的字母列表。

_column_name_generator() = ['A', 'B', ..., 'AA', 'AB', ..., 'BA', 'BB', ..., 'CV']

然后我可以结合一些有限列表对其进行迭代,例如0-10。请参阅下面的代码。我想要的是创建一个生成器,它会给我一个无限长的递增字母列表。

import string


def _column_name_generator():
    column_names = []
    for x in range(0, 100):
        if x < 26:
            column_names.append(string.ascii_uppercase[x % 26])
        else:
            column_names.append(column_names[x/26 - 1] + string.ascii_uppercase[x % 26])
    return column_names

container = []
for column_name, num in zip(_column_name_generator(), range(0, 10)):
    container.append(column_name + str(num))

print _column_name_generator()
print container

container = ['A0', 'B1', 'C2', 'D3', 'E4', 'F5', 'G6', 'H7', 'I8', 'J9']

每次都yield column_names的最后一个元素,用itertools.count代替range提供无限增加:

import itertools

def _column_name_generator():
    column_names = []
    for x in itertools.count():
        if x < 26:
            column_names.append(string.ascii_uppercase[x % 26])
        else:
            column_names.append(column_names[x/26 - 1] + string.ascii_uppercase[x % 26])
        yield column_names[-1]

一个更好的解决方案是

import itertools, string

def _column_name_generator():
    for i in itertools.count(1):
        for p in itertools.product(string.ascii_uppercase, repeat=i):
            yield ''.join(p)

它基本上迭代长度 i 大写 ascii 字母(每个可能的序列)的乘积,当 i 逐渐增加时,从 1 开始(AB, C).

一种不那么 pythonic 的方式

正如您的问题所暗示的那样,一种方法是在每一步将余数除以 26 并将余数转换为字母,直到除法 return 0。使用 %(取模)得到余数, // (floor division) 更新下一步的值。这可能是代码:

numberOfElements = 100
letters = []
for counter in range(numberOfElements):
    i = counter
    newCharacter = i % 26
    i //= 26
    s = "" +chr(newCharacter + ord('A') )
    while i != 0:
        newCharacter = i % 26
        i //= 26
        s = chr(newCharacter + ord('A') ) + s
    letters.append(s)
print letters

结果:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'BA', 'BB', 'BC', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BK', 'BL', 'BM', 'BN', 'BO', 'BP', 'BQ', 'BR', 'BS', 'BT', 'BU', 'BV', 'BW', 'BX', 'BY', 'BZ', 'CA', 'CB', 'CC', 'CD', 'CE', 'CF', 'CG', 'CH', 'CI', 'CJ', 'CK', 'CL', 'CM', 'CN', 'CO', 'CP', 'CQ', 'CR', 'CS', 'CT', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DA', 'DB', 'DC', 'DD', 'DE', 'DF', 'DG', 'DH', 'DI', 'DJ', 'DK', 'DL', 'DM', 'DN', 'DO', 'DP', 'DQ', 'DR', 'DS', 'DT', 'DU', 'DV']