2015-08-28 77 views
0

我有這樣增量字母的Python

['AX95', 'BD95'] 

我需要從AX95開始名單擴大到BD95這樣

['AX95', 'AY95', 'AZ95', 'BA95','BB95','BC95','BD95'] 

我當前的代碼列表工作正常,單字母像

['A95', 'D95'] 

我的代碼現在看起來像這樣,

import re 


def resolve(item): 
    start = int(re.search(r'\d+', item[0]).group()) 
    end = int(re.search(r'\d+', item[1]).group()) 
    print(item) 
    c = re.search(r'[a-zA-Z]+', item[0]).group() 
    d = re.search(r'[a-zA-Z]+', item[1]).group() 
    print(c, d) 
    for char in range(ord(c), ord(d) + 1): 
     yield chr(char) + str(end) 


xx = resolve(['AX95', 'BD95']) 

print(list(xx)) 

如何做到這一點?

+0

拆分這個分解成更小的問題,而不是試圖解決它的所有功能於一體;一方面,您在當前代碼中有不必要的重複。 – jonrsharpe

+0

你的意思是隻擴展左邊兩位'[A-Z]'指定的? – luoluo

+0

是的。指定開始和結束範圍。 – PyAn

回答

4

您不能直接在多個字符使用ord(),它會出錯誤與錯誤 -

TypeError: ord() expected a character, but string of length 2 found 

而且,這將是非常複雜與for環和range()要做到這一點,我會建議使用while循環並檢查,直到開始字符變成結束字符。

做到這一點的一種方法是獲取最後一個元素,檢查它的Z是否將其更改爲A並在其之前增加元素。否則將其ord()增量1,然後使用chr()獲取該字符。

例算法上字符的任意大小的作品 -

def resolve(item): 
    start = int(re.search(r'\d+', item[0]).group()) 
    c = re.search(r'[a-zA-Z]+', item[0]).group() 
    d = re.search(r'[a-zA-Z]+', item[1]).group() 
    print(c, d) 
    s = c 
    yield s + str(start) 
    while s != d: 
     ls = len(s) - 1 
     news = "" 
     for i in range(ls,-1,-1): 
      c = s[i] 
      if c.upper() == 'Z': 
       news += 'A' 
      else: 
       news += chr(ord(c) + 1) 
       break 
     s = s[:i] + news[::-1] 
     yield s + str(start) 

示例/演示 -

>>> def resolve(item): 
...  start = int(re.search(r'\d+', item[0]).group()) 
...  c = re.search(r'[a-zA-Z]+', item[0]).group() 
...  d = re.search(r'[a-zA-Z]+', item[1]).group() 
...  print(c, d) 
...  s = c 
...  yield s + str(start) 
...  while s != d: 
...   ls = len(s) - 1 
...   news = "" 
...   for i in range(ls,-1,-1): 
...    c = s[i] 
...    if c.upper() == 'Z': 
...     news += 'A' 
...    else: 
...     news += chr(ord(c) + 1) 
...     break 
...   s = s[:i] + news[::-1] 
...   yield s + str(start) 
... 
>>> 
>>> xx = resolve(['AX95', 'BD95']) 
>>> 
>>> print(list(xx)) 
AX BD 
['AX95', 'AY95', 'AZ95', 'BA95', 'BB95', 'BC95', 'BD95'] 
1

給你:)

import re 

def resolve(item): 
    print (item) 
    num = int(re.search(r'\d+', item[0]).group()) 
    p11 = re.search(r'(\w)(\w)', item[0]).group(1) 
    p12 = re.search(r'(\w)(\w)', item[0]).group(2) 
    p21 = re.search(r'(\w)(\w)', item[1]).group(1) 
    p22 = re.search(r'(\w)(\w)', item[1]).group(2) 
    print (p11, p12, p21, p22) 
    for word in range(ord(p11), ord(p21) + 1): 
     for word2 in range(ord(p12) if ord(p11) == word else ord('A'), (ord(p22) if ord(p21) == word else ord('Z')) + 1): 
      yield chr(word) + chr(word2) + str(num) 
+0

相同的「for」(for word2 ..),你可以重複對於3號和4號位置的數字 –

1

這是一種替代方法,其還應該應付翻身。

它首先從開始和結束範圍分開字母和數字。兩個字母組然後被轉換爲基數爲27的數字。目標是從開始到結束簡單計數。

然後使用Python的itertools.product創建一個AAZZ的序列,其中itertools.islice提供了必要的範圍。

爲什麼選擇27?這是一種類似於處理前導零的解決方法。即將AAAAA轉換爲基數26將給出相同的值。

import string, itertools, re 

def convert_to_range(chars): 
    value = 0 
    for index, unit in enumerate([ord(x) - 64 for x in reversed(chars)]): 
     value += unit * (27 ** index) 
    return value 

def resolve(item): 
    start_split = re.split("(\d+)", item[0]) 
    end_split = re.split("(\d+)", item[1]) 
    trailing = end_split[1] 
    start = convert_to_range(start_split[0]) 
    end = convert_to_range(end_split[0]) 
    cols = [' '+string.ascii_uppercase] * len(end_split[0]) 

    for x in itertools.islice(itertools.product(*cols), start, end+1): 
     step = "".join(x).lstrip(" ") 
     if ' ' in step: 
      continue 
     yield step + trailing 

print(list(resolve(['AX95', 'BD95']))) 
print(list(resolve(['X95', 'AA95']))) 
print(list(resolve(['ZX95', 'AAB95']))) 

這將使你:

['AX95', 'AY95', 'AZ95', 'BA95', 'BB95', 'BC95', 'BD95'] 
['X95', 'Y95', 'Z95', 'AA95'] 
['ZX95', 'ZY95', 'ZZ95', 'AAA95', 'AAB95']