2010-07-16 101 views
5

在Perl中,要獲得從「a」到「azc」的所有字符串的列表,只需要做的事情是使用範圍運算符:什麼是python相當於perl「a」..「azc」

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

我要的是一個字符串列表:

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

我想我可以使用ordchr,循環一遍又一遍,這是簡單的獲得「A」到「Z」,例如:

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

但我的情況稍微複雜一些,在這裏。

感謝您的幫助!

回答

4

發電機版本:

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 

編輯: @ihightower要求在評論:

如果我想從'b'打印到'azc',我不知道該怎麼辦。

所以你想從'a'以外的東西開始。開始前值只是丟棄任何東西:

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

是啊!絕對好(不能投票,因爲我只有11的聲望,但聲音正確!) – 2010-07-16 12:16:13

+0

偉大的答案麥克! – ninetwozero 2013-01-17 11:06:29

+0

可能是很好的答案......但是,如何使用這個......作爲一個新手......如果我想從'b'打印到'azc',我不知道該怎麼辦。我從字母「b」重複字母「azc」。功能可能不錯,但作爲初學者,我不知道如何使用它來完成實際的工作和打印。 – ihightower 2013-05-13 15:32:25

2

在itertools中使用產品調用,在字符串中使用ascii_letters。

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

它應該是'ascii_lowercase',而你還沒有佔到在「AZC」停止。 – 2010-07-16 11:44:33

+0

嗯,謝謝,在這裏我可以有一個從字符串列表到zzz。所以我會做第二個循環來將項目從第一個循環複製到第二個循環,並在遇到「結束」字符串時停止。 我會用完整的代碼示例回答我的問題。非常感謝 ! – 2010-07-16 11:49:33

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

與此有關的主要問題:1)使用'xrange'而不是'range'。由於'range'是一個生成器,並且不會預先生成結果列表,所以'xrange'不再有'range'的優勢。因此'xrange'不推薦使用,而IIRC,甚至不使用Python 3. 2)當你可以剛剛使用'list.index()'和slice操作時,從'values'構造'endvalues'。3)這不是如何將問題標記爲在SO上回答的問題。 – 2010-07-16 12:15:59

+2

@Mike,Python 2.7中仍然需要'xrange',它在不到2周前發佈。 'range'仍然返回一個列表。 – 2010-07-16 12:21:33

+0

我已經更新了這個使用切片和索引()。還刪除了包裝文字。 – 2010-07-16 12:28:53

4

一個建議完全基於迭代器:

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

這裏有一個更好的方式來做到這一點,但你需要一個轉換功能:

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

而且這裏是你的函數(謝謝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 

我加上了小寫轉換選項,以防萬一你想這樣做。

1

我全身接受的答案才能夠啓動中,比小寫使用其他:

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)) 
相關問題