Updated, 11 December 2010
Here’s some code to generate an arbitrary unique sequence of any combination of numbers, letters, or any character other than whitespace. (See also “Old Post” below for more on the what and why.)
I turned this into a class that implements the iterator protocol, and added a unit test module. I may have went overboard with the unit testing, but I looked at it as a learning exercise, and it’s kind of rewarding in a deep and meaningful way to be able to press a button and put a module through its paces. Final code counts:
The code is now released with the GNU GPL license v3:
It’s written for Python 2.6, but I ran the files through the 2to3 tool with an eye to an easy conversion to Python 3.
The constructor takes two parameters. The first is stoplen. The sequence will stop generating new values when the length of the next value equals stoplen. The second is the sequence “alphabet.” The default is an alphanumeric sequence. You can also specify a rollover len where it will reset to “zero” (the first character in the sequence’s alphabet) when the next value equals rollover_len.
So, you might use it in an iteration context:
>>> from sequence_generator import SeqGen >>> for i in SeqGen(3, 'ABC'): ... print i.rjust(2, 'A') ... AB AC BA BB BC CA CB CC
Or you might try:
>>> s = SeqGen() >>> s.seqchars '0123456789abcdefghijklmnopqrstuvwxyz' >>> next(s) '1' >>> next(s) '2' >>> s.rollover_len = 5 >>> s.value = 'zzzy' >>> next(s) 'zzzz' >>> next(s) '1'
Or you may revel in the beauty of a (hopefully!) comprehensive set of unit tests:
$ ./sequence_generator_test.py -v ALPHANUM_26 sequence ... ok ALPHANUM_36 sequence ... ok ALPHANUM_62 sequence ... ok binary sequence ... ok default (ALPHANUM_36) sequence ... ok HEX sequence ... ok LETTERS sequence ... ok base numbers and letters ... ok NUMBERS sequence ... ok __init__ input parameter validation ... ok iteration / stop iteration ... ok main with bad input ... ok main with good input ... ok rollover ... ok seqchars ... ok get_value ... ok set_value ... ok validate ... ok ----------------------------------------------- Ran 18 tests in 0.227s OK
I was looking for Python “sequence generator” code earlier today. By that, I’m thinking of a method to increment an arbitrary string of letters and numbers in an orderly way.
I figured there should be code samples out there to make quick work of it, but it was more challenging to find something than expected. Part of it might be my weak conceptual grasp of the subject. Maybe I just lacked the necessary search terms. With the words I did have — sequence and generator — I got a lot of static since these terms describe basic Python concepts.
I finally resorted to crafting my own sequence generator. To you, Future Searcher, I hope it will be useful. It is easy enough to convert this into a function, which I did for my script. (Or maybe you’ll want an actual generator!) I won’t elaborate on it more. If you’re looking for this, you probably know everything you need to know.
#!/usr/bin/python3 import sys if len(sys.argv) < 2: last_value = ' ' else: last_value = ' ' + sys.argv.strip() next_value = '' # alphabet: first character must repeat at end so we can detect digit rollover # hex = '0123456789abcdef0' # 36 chars = '0123456789abcdefghijklmnopqrstuvwxyz0' # 62 chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0' # 28 chars = '23456789BCDFGHJKMNPQRSTVWXYZ2' # (dropping 0, 1, and vowels to avoid confusion and actual words) alphabet = '0123456789abcdefghijklmnopqrstuvwxyz0' increment = True for x in reversed(last_value): # walk backwards, incrementing as necessary if x == ' ': # reached the beginning if increment: # all chars rolled over: grow a digit x = alphabet # create new leftmost "zero" to count from else: break # we're done if increment: next_alphabet_idx = alphabet.find(x) + 1 this_char = alphabet[next_alphabet_idx] if next_alphabet_idx + 1 < len(alphabet): increment = False # we're done "rolling" else: this_char = x next_value = this_char + next_value # building new value right to left # print(next_value.strip()) print('last value = ' + last_value.strip()) print('next value = ' + next_value)