2011-08-16 29 views
28

estoy generando todas las posibles palabras clave e.g. aaa, aab, aac.... zzy, zzz tres letras continuación es mi código:¿Cuál es la mejor manera de generar todas las posibles cadenas de tres letras?

alphabets = ['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'] 

keywords = [] 
for alpha1 in alphabets: 
    for alpha2 in alphabets: 
     for alpha3 in alphabets: 
      keywords.append(alpha1+alpha2+alpha3) 

se puede lograr esta funcionalidad de una manera más elegante y eficiente?

Respuesta

68
keywords = itertools.product(alphabets, repeat = 3) 

Ver el documentation for itertools.product. Si necesita una lista de cadenas, sólo tiene que utilizar

keywords = [''.join(i) for i in itertools.product(alphabets, repeat = 3)] 

alphabets también no tiene que ser una lista, que sólo puede ser una cadena, por ejemplo:

from itertools import product 
from string import ascii_lowercase 
keywords = [''.join(i) for i in product(ascii_lowercase, repeat = 3)] 

funcionará si sólo quiere el lowercase ascii letters.

+0

Si desea generar cada combinación de caracteres sobre la marcha sin ocupar una gran cantidad de memoria, puede cambiar '[ '' .join (i) para i en el producto (ascii_lowercase, repetir = 3)]' a '('' .join (i) para i en producto (ascii_lowercase, repeat = 3))' e iterar a través de cada uno en un bucle 'for-in' – DCIndieDev

13

También es posible usar un mapa en lugar de la lista por comprensión (este es uno de los casos en un mapa sigue siendo más rápido que el LC)

>>> from itertools import product 
>>> from string import ascii_lowercase 
>>> keywords = map(''.join, product(ascii_lowercase, repeat=3)) 

Esta variación de la lista por comprensión es también más rápido que usar ''.join

>>> keywords = [a+b+c for a,b,c in product(ascii_lowercase, repeat=3)] 
+2

Con' join' no tiene que cambiarlo si cambias el valor de 'repeat' - agrega un cliché sobre la optimización prematura aquí. – agf

3
from itertools import combinations_with_replacement 

alphabets = ['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'] 

for (a,b,c) in combinations_with_replacement(alphabets, 3): 
    print a+b+c 
+1

Esto no es realmente lo mismo. Pruébalo con dos letras: obtienes 26 combinaciones con 'a' como primera letra, luego 25 para' b', etc., hasta 'zz' para' z' como primera letra. Es decir, no obtienes tanto 'ab' como' ba', o para usar el ejemplo en el OP, no obtienes 'zzy', porque ya tienes' yzz'. – agf

+0

hmm, ya veo. Gracias por señalar eso. – Asterisk

2
chars = range(ord('a'), ord('z')+1); 
print [chr(a) + chr(b) +chr(c) for a in chars for b in chars for c in chars] 
3

también puede hacer esto sin ningún tipo de módulos externos haciendo s cálculo de imple.
El PermutationIterator es lo que está buscando.

def permutation_atindex(_int, _set, length): 
    """ 
    Return the permutation at index '_int' for itemgetter '_set' 
    with length 'length'. 
    """ 
    items = [] 
    strLength = len(_set) 
    index = _int % strLength 
    items.append(_set[index]) 

    for n in xrange(1,length, 1): 
     _int //= strLength 
     index = _int % strLength 
     items.append(_set[index]) 

    return items 

class PermutationIterator: 
    """ 
    A class that can iterate over possible permuations 
    of the given 'iterable' and 'length' argument. 
    """ 

    def __init__(self, iterable, length): 
     self.length = length 
     self.current = 0 
     self.max = len(iterable) ** length 
     self.iterable = iterable 

    def __iter__(self): 
     return self 

    def __next__(self): 
     if self.current >= self.max: 
      raise StopIteration 

     try: 
      return permutation_atindex(self.current, self.iterable, self.length) 
     finally: 
      self.current += 1 

Déle un objeto iterable y un entero como la longitud de salida.

from string import ascii_lowercase 

for e in PermutationIterator(ascii_lowercase, 3): 
    print "".join(e) 

Esto comenzará desde 'aaa' y terminará con 'zzz'.

-1
print([a+b+c for a in alphabets for b in alphabets for c in alphabets]) 
Cuestiones relacionadas