2015-08-28 3 views
0

У меня есть список, как этотIncrement алфавит 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) 

Пример/Demo -

>>> 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

одинаковые« для »(для слова2 ..) для чисел в 3 и 4 позиции –

1

Вот альтернативный подход, который также должны справиться с переходом.

Он работает, сначала разбивая буквы и цифры из диапазона начала и конца. Затем две буквенные группы преобразуются в базовые числа 27. Цель состоит в том, чтобы затем просто рассчитывать от начала и до конца.

Питона itertools.product затем используется для создания последовательности AA в ZZ с itertools.islice, обеспечивающей необходимый диапазон.

Почему база 27? Это был обходной путь, похожий на дело с ведущими нулями. то есть преобразование AA и AAA к основанию 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'] 
Смежные вопросы