2010-07-16 3 views
5

En perl, pour obtenir une liste de toutes les chaînes de "a" à "azc", à seulement chose à faire est d'utiliser l'opérateur de gamme:Quel est le python équivalent à perl "a" .. "azc"

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

ce que je veux une liste de chaînes:

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

Je suppose que je peux utiliser ord et chr, bouclez et plus, est simple à obtenir pour « a » à « z », par exemple :

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

Mais un peu plus complexe pour mon cas, ici.

Merci pour toute aide!

Répondre

4

Version Générateur:

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 demande dans les commentaires:

Je n'ai aucune idée de ce que je devrais faire si je veux imprimer de 'b' à 'azc'.

Donc, vous voulez commencer par autre chose que 'a'. Il suffit de jeter quoi que ce soit avant que la valeur de départ:

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

ouais! Définitivement bien (je ne peux pas voter car je n'ai que 11 points de réputation, mais ça sonne bien!) –

+0

Bonne réponse Mike! – ninetwozero

+0

Pourrait être une bonne réponse ... Mais, Comment utilise-t-on ... En tant que débutant ... Je n'ai aucune idée de ce que je devrais faire si je veux imprimer de 'b' à 'azc'. Je répète de la lettre "b" à la lettre "azc". La fonction peut être bonne ... mais en tant que débutant, je n'ai aucune idée de comment je pourrais l'utiliser pour faire le travail et l'impression. – ihightower

2

Utilisez l'appel du produit dans itertools, et ascii_letters from string.

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

Il devrait être 'ascii_lowercase', et vous n'avez pas encore pris en compte pour arrêter à « azc ». –

+0

hmm, merci, ici je peux avoir une liste de chaîne de a à zzz. Je vais donc faire une seconde boucle pour copier les éléments de la première boucle vers la seconde, et arrêter en rencontrant la chaîne "end". Je vais répondre à ma question avec un exemple de code complet. Merci beaucoup ! –

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

Problèmes majeurs avec ceci: 1) Utilisation de 'xrange' au lieu de' range'. 'xrange' n'a plus d'avantage sur' range', puisque 'range' est un générateur et ne pré-génère pas la liste des résultats. Ainsi, 'xrange' est obsolète, et IIRC, pas même en Python 3. 2) Construire' endvalues' à partir de 'values' alors que vous auriez pu utiliser' list.index() 'et une opération de découpe.3) Ce n'est pas comme ça que vous marquez les questions auxquelles vous avez répondu SO. –

+2

@Mike, 'xrange' est toujours requis dans Python 2.7, qui a été publié il y a moins de deux semaines. 'range' renvoie toujours une liste. –

+0

J'ai mis à jour celui-ci pour utiliser les tranches et index(). Également supprimé le texte d'emballage. –

4

Une suggestion purement basée sur itérateurs:

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

Voici une meilleure façon de le faire, si vous avez besoin d'une fonction de conversion:

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

Et voici votre fonction (merci 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 

J'ai viré sur l'option de conversion en minuscules, juste au cas où vous le vouliez.

1

Je généralise la réponse acceptée pour être en mesure de commencer à moyen et à utiliser autre que minuscules:

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)) 
Questions connexes