增量字母Python

时间:2015-08-28 09:14:07

标签: 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))

怎么做?

3 个答案:

答案 0 :(得分: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 :(得分: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)

答案 2 :(得分: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']