2010-07-16 14 views
5

En perl, para obtener una lista de todas las cadenas de "a" a "azc", solo hacer es usar el operador de rango:¿Cuál es el equivalente de python a "a" .. "azc"

perl -le 'print "a".."azc"' 

Lo que yo quiero es una lista de cadenas:

["a", "b", ..., "z", "aa", ..., "az" ,"ba", ..., "azc"] 

supongo que puedo utilizar ord y chr, de enlace y otra vez, esto es fácil de conseguir para "a" a la "z", por ejemplo, :

>>> [chr(c) for c in range(ord("a"), ord("z") + 1)] 
['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'] 

Pero un poco más complejo para mi caso, aquí.

¡Gracias por cualquier ayuda!

Respuesta

4

Generador:

from string import ascii_lowercase 
from itertools import product 

def letterrange(last): 
    for k in range(len(last)): 
     for x in product(ascii_lowercase, repeat=k+1): 
      result = ''.join(x) 
      yield result 
      if result == last: 
       return 

EDIT: @ihightower pregunta en los comentarios:

No tengo idea de qué debería hacer si quiero imprimir de 'b' a 'azc'.

Por lo que desea comenzar con algo que no sea 'a'. Simplemente descartar cualquier cosa antes de que el valor de inicio:

def letterrange(first, last): 
    for k in range(len(last)): 
     for x in product(ascii_lowercase, repeat=k+1): 
      result = ''.join(x) 
      if first: 
       if first != result: 
        continue 
       else: 
        first = None 
      yield result 
      if result == last: 
       return 
+0

sí! Definitivamente bien (no puedo votar, ya que tengo solo 11 reputación, pero ¡está bien!) –

+0

¡Gran respuesta, Mike! – ninetwozero

+0

Podría ser una gran respuesta ... Pero, ¿cómo se usa esto ... Como novato ... No tengo idea de qué hacer si quiero imprimir de 'b' a 'azc'. Repito desde la letra "b" a la letra "azc". La función puede ser buena ... pero como principiante no tengo idea de cómo podría usarla para hacer el trabajo real e imprimir. – ihightower

2

Use la llamada al producto en itertools, y ascii_letters de la cadena.

from string import ascii_letters 
from itertools import product 

if __name__ == '__main__': 
    values = [] 
    for i in xrange(1, 4): 
     values += [''.join(x) for x in product(ascii_letters[:26], repeat=i)] 

    print values 
+0

Debe ser 'ascii_lowercase', y que aún no se han representado con parada en 'AZC'. –

+0

hmm, gracias, aquí puedo tener una lista de cadenas de a a zzz. Así que haré un segundo ciclo para copiar los elementos del primer ciclo al segundo y me detendré al encontrar la cadena "final". Responderé a mi pregunta con un ejemplo de código completo. Muchas gracias ! –

0
def strrange(end): 
    values = [] 
    for i in range(1, len(end) + 1): 
     values += [''.join(x) for x in product(ascii_lowercase, repeat=i)] 
    return values[:values.index(end) + 1] 
+0

Principales problemas con esto: 1) Uso de 'xrange' en lugar de' range'. 'xrange' ya no tiene ninguna ventaja sobre' range', ya que 'range' es un generador y no pregenera la lista de resultados. Por lo tanto, 'xrange' está en desuso, e IIRC, ni siquiera en Python 3. 2) Construyendo' endvalues' from 'values' cuando podrías haber usado' list.index() 'y una operación de corte.3) Esta no es la forma en que marca las preguntas como se contestó en SO. –

+2

@Mike, 'xrange' todavía se requiere en Python 2.7, que se lanzó hace menos de 2 semanas. 'range' aún devuelve una lista. –

+0

He actualizado este para usar slices e index(). También eliminó el texto de envoltura. –

4

Una sugerencia puramente basado en iteradores:

versión
import string 
import itertools 

def string_range(letters=string.ascii_lowercase, start="a", end="z"): 
    return itertools.takewhile(end.__ne__, itertools.dropwhile(start.__ne__, (x for i in itertools.count(1) for x in itertools.imap("".join, itertools.product(letters, repeat=i))))) 

print list(string_range(end="azc")) 
1

Aquí hay una mejor manera de hacerlo, aunque se necesita una función de conversión:

for i in xrange(int('a', 36), int('azd', 36)): 
    if base36encode(i).isalpha(): 
     print base36encode(i, lower=True) 

Y aquí está su función (gracias Wikipedia):

def base36encode(number, alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ', lower=False): 
    ''' 
    Convert positive integer to a base36 string. 
    ''' 
    if lower: 
     alphabet = alphabet.lower() 
    if not isinstance(number, (int, long)): 
     raise TypeError('number must be an integer') 
    if number < 0: 
     raise ValueError('number must be positive') 

    # Special case for small numbers 
    if number < 36: 
     return alphabet[number] 

    base36 = '' 
    while number != 0: 
     number, i = divmod(number, 36) 
     base36 = alphabet[i] + base36 

    return base36 

He marcado la opción de conversión en minúscula, en caso de que lo desee.

1

que generalizar la respuesta aceptada para poder empezar a medio y a los usos distintos minúsculas:

from string import ascii_lowercase, ascii_uppercase 
from itertools import product 

def letter_range(first, last, letters=ascii_lowercase): 
    for k in range(len(first), len(last)): 
     for x in product(letters, repeat=k+1): 
      result = ''.join(x) 
      if len(x) != len(first) or result >= first: 
       yield result 
       if result == last: 
        return 
print list(letter_range('a', 'zzz')) 
print list(letter_range('BA', 'DZA', ascii_uppercase)) 
Cuestiones relacionadas