2015-08-28 53 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']