将起始索引添加到字符串索引生成器

Posted

技术标签:

【中文标题】将起始索引添加到字符串索引生成器【英文标题】:Add a start index to a string index generator 【发布时间】:2017-09-22 09:41:31 【问题描述】:

我目前正在学习创建生成器和使用itertools。所以我决定制作一个字符串索引生成器,但我想添加一些参数,例如“开始索引”,允许定义从哪里开始生成索引。

我想出了这个丑陋的解决方案,它可能会很长而且对大索引效率不高:

import itertools
import string

class StringIndex(object):
    '''
    Generator that create string indexes in form:
    A, B, C ... Z, AA, AB, AC ... ZZ, AAA, AAB, etc.
    
    Arguments:
    - startIndex = string; default = ''; start increment for the generator.
    - mode = 'lower' or 'upper'; default = 'upper'; is the output index in
      lower or upper case.
    '''
    
    def __init__(self, startIndex = '', mode = 'upper'):
        
        if mode == 'lower':
            self.letters = string.ascii_lowercase
        
        elif mode == 'upper':
            self.letters = string.ascii_uppercase
        
        else:
            cmds.error ('Wrong output mode, expected "lower" or "upper", ' + 
                        'got '.format(mode))
        
        if startIndex != '':
            if not all(i in self.letters for i in startIndex):
                cmds.error ('Illegal characters in start index; allowed ' + 
                            'characters are: '.format(self.letters))
        
        self.startIndex = startIndex
    
    
    def getIndex(self):
        '''
        Returns:
        - string; current string index
        '''
        startIndexOk = False
        x = 1
        while True:
            strIdMaker = itertools.product(self.letters, repeat = x)
            
            for stringList in strIdMaker:
                index = ''.join([s for s in stringList])
                
                # Here is the part to simpify
                if self.startIndex:
                    if index == self.startIndex:
                        startIndexOk = True
                    
                    if not startIndexOk:
                        continue
                ###
                
                yield index
            x += 1

欢迎任何建议或改进。谢谢!

编辑: 起始索引必须是字符串!

【问题讨论】:

【参考方案1】:

您必须自己进行算术运算(以 26 为基数)以避免循环遍历 itertools.product。但是你至少可以设置x=len(self.startIndex) or 1

【讨论】:

【参考方案2】:

旧的(不正确的)答案

如果您不使用 itertools(假设您以单个字母开头),您可以执行以下操作:

letters = 'abcdefghijklmnopqrstuvwxyz'
def getIndex(start, case):
    lets = list(letters.lower()) if case == 'lower' else list(letters.upper())
    # default is 'upper', but can also be an elif

    for r in xrange(0,10):
        for l in lets[start:]:
            if l.lower() == 'z':
                start = 0
            yield ''.join(lets[:r])+l

我会一直运行,直到创建最多 10 行字母,但您当然可以使用无限 while 循环,这样它就可以永远被调用。

正确答案

我以不同的方式找到了解决方案:我使用了一个以 26 为基数的数字转换器(基于(并已修复,因为它不能完美运行):http://quora.com/How-do-I-write-a-program-in-Python-that-can-convert-an-integer-from-one-base-to-another)

我使用 itertools.count() 来计算并循环所有可能性。

代码:

import time
from itertools import count

def toAlph(x, letters):
    div = 26
    r = '' if x > 0 else letters[0]
    while x > 0:
        r = letters[x % div] + r
        if (x // div == 1) and (x % div == 0):
            r = letters[0] + r
            break
        else:
            x //= div
    return r

def getIndex(start, case='upper'):
    alphabet = 'abcdefghijklmnopqrstuvwxyz'
    letters = alphabet.upper() if case == 'upper' else alphabet

    started = False
    for num in count(0,1):
        l = toAlph(num, letters)
        if l == start:
            started = True

        if started:
            yield l

iterator = getIndex('AA')
for i in iterator:
    print(i)
    time.sleep(0.1)

【讨论】:

对不起,如果不清楚,但我希望起始索引是一个字符串。此外,如果索引> 25,它似乎不起作用。最后,在“AZ”之后,我得到的是“ABA”而不是“BA”。 抱歉,不太明白你的意思。考虑到这个问题,我认为您可能需要像递归生成器这样的东西,因为您实际上是在无限深度的树结构上循环。 谢谢。还有另一个问题。如果我从“AAZ”之后的索引开始,我会陷入无限循环。

以上是关于将起始索引添加到字符串索引生成器的主要内容,如果未能解决你的问题,请参考以下文章

Pandas处理dataframe的文本数据列:使用str属性获取数据列的字符串方法类使用方括号索引根据起始索引抽取字符串内容的子字符串(如果只有一个数字默认索引到字符串结束)

JavaScript基础 substring() 返回 起始索引值 到 结束索引值 之间的所有字符

Pandas处理dataframe的文本数据列:使用str属性获取数据列的字符串方法类slice函数根据起始索引抽取字符串内容的子字符串(如果只有一个数字默认索引到字符串结束)

java 字符串转换成日期

将带有字符串索引的运行数字添加到 Spark 中的数据框?

字符串生成器