Generar cadenas alfanuméricas secuencialmente.

Estoy tratando de crear un bucle para generar e imprimir cadenas de la siguiente manera:

  1. Sólo caracteres alfanuméricos:
  2. 0-9 están antes de AZ, que están antes de az,
  3. La longitud sube hasta 4 caracteres.

Por lo tanto, se imprimiría:

  1. todas las cadenas de 0-z
  2. entonces de 00-zz
  3. entonces de 000-zzz
  4. entonces desde 0000-zzzz

entonces se detiene.

from string import digits, ascii_uppercase, ascii_lowercase from itertools import product chars = digits + ascii_uppercase + ascii_lowercase for n in range(1, 4 + 1): for comb in product(chars, repeat=n): print ''.join(comb) 

Este primero hace una cadena de todos los números, letras mayúsculas y letras minúsculas.

Luego, para cada longitud del 1 al 4, imprime cada combinación posible de esos números y letras.

Tenga en cuenta que esto es MUCHAS combinaciones – 62 ^ 4 + 62 ^ 3 + 62 ^ 2 + 62.

No me gusta la respuesta dada antes de usar el product ya que al ver su implementación en la documentación de python, parece abarcar todo en una lista en la memoria antes de comenzar a producir los resultados.

Esto es muy malo para su caso ya que, como lo dijo el propio AGF, el número de permutaciones aquí es enorme (más de un millón). Para este caso, se creó la statement de yield , de modo que se podrían generar dinámicamente enormes listas en lugar de abarcarlas en la memoria (también me disgustó el range desperdicio en el que xrange es perfectamente aplicable).

Me gustaría una solución como esta:

 def generate(chars, length, prefix = None): if length < 1: return if not prefix: prefix = '' for char in chars: permutation = prefix + char if length == 1: yield permutation else: for sub_permutation in generate(chars, length - 1, prefix = permutation): yield sub_permutation 

De esta manera, todo lo que se extiende en la memoria es una stack recursiva "n" profunda, donde "n" es la longitud de sus permutaciones (4 en este caso) y solo se devuelve un solo elemento cada vez.

chars es el conjunto de caracteres para elegir, la longitud es 4 y el uso es bastante similar al de los productos, excepto que no abarca toda la lista en la memoria durante el tiempo de ejecución.

Codifiqué esto hoy. Hace exactamente lo que quieres y más . Es extensible tambien

 def lastCase (lst): for i in range(0, len(lst)): if ( lst[i] != '_' ): return False return True l = [''] * 4 #change size here if needed. I used 4 l[0] = '0' index = 0 while ( not lastCase(l) ): if ( ord(l[index]) > ord('_') ): l[index] = '0' index += 1 while( l[index] == '_' ): l[index] = '0' index += 1 if (l[index] == ''): l[index] = '0' #print or process generated string print(''.join(l)) l[index] = chr(ord(l[index]) +1) if ( ord(l[index]) > ord('9') and ord(l[index]) < ord('A') ): l[index] = 'A' elif ( ord(l[index]) > ord('Z') and ord(l[index]) < ord('_') ): l[index] = '_' index = 0 print (''.join(l)) 
 from string import digits, ascii_uppercase, ascii_lowercase from itertools import product chars = digits + ascii_uppercase + ascii_lowercase def give_me_next(lst): lst = lst[::-1] change_next = False change = True n = 0 for x in lst: if change_next == True: change_next = False pos = chars.find(x) try: a = chars[pos+1] lst = list(lst) lst[n] = a lst = "".join(lst) x = a except: lst = list(lst) lst[n] = '0' lst = "".join(lst) change_next = True x = '0' pos = chars.find(x) try: a = chars[pos+1] if change == True: lst = list(lst) lst[n] = a lst = "".join(lst) change = False except: lst = list(lst) lst[n] = '0' lst = "".join(lst) change_next = True n = n + 1 lst = lst[::-1] return lst a= give_me_next('zzzzz') while True: a = give_me_next(a) print a 

Esta me parece la solución más simple:

 from string import digits, ascii_uppercase, ascii_lowercase chars = digits + ascii_uppercase + ascii_lowercase all_str = [''.join([a]) for a in chars] \ + [''.join([a,b]) for a in chars for b in chars] \ + [''.join([a,b,c]) for a in chars for b in chars for c in chars] \ + [''.join([a,b,c,d]) for a in chars for b in chars for c in chars for d in chars] print(all_str) print("Number of strings:", len(all_str)) 

Ejemplo para cadenas con un máximo de 2 caracteres.

Por supuesto, puede haber una forma de generalizar a cualquier número máximo de caracteres por cadena, pero como tiene una necesidad específica de cadenas de hasta 4 caracteres, está bien.