I've created a function that generates a list of alphabets incrementing continuously. A, B, C ..., Z. After Z, it goes to AA, AB, AC ...AZ. This pattern repeats. This is similar to MS Excel's column names. At the moment, this function generates a finite list of alphabets.
_column_name_generator() = ['A', 'B', ..., 'AA', 'AB', ..., 'BA', 'BB', ..., 'CV']
I can then iterate over it in conjunction with some finite list, e.g. 0-10. See my code below. What I'd like is to create a generator that will give me an infinitely long list of incrementing alphabets.
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']
Iterator in Python is any python type that can be used with a ' for in loop '. Python lists, tuples, dictionaries, and sets are all examples of inbuilt iterators. But it is not necessary that an iterator object has to exhaust, sometimes it can be infinite.
We will use the built-in Python function chr() to print the small alphabets from a to z. We know that the Ascii code of 'a' is 97 and that of 'z' is 122. Therefore we will use a range() function in a for loop with arguments 97, 123. This for loop will print a to z alphabets.
Yield column_names
's last element every time, and use itertools.count
instead of range
to provide infinite increase:
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]
A better solution, altering the original code but dismissing the need in a memory consuming list of column_names
, would be
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)
it basically iterates over the product of length i
the uppercase ascii letters (every sequence possible) when i is gradually increasing, starting from 1
(A
, B
, C
).
A less pythonic way
As implied in your question, one way is dividing by 26 converting the remainder into a letter at every step, until the division return 0. Use %
(modulo) to get the remainder, //
(floor division) to update the value for the next step. This could be the code:
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
Result:
['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']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With