2017-09-22 4 views
0

現在、ジェネレータを作成し、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 

。ありがとうございました!

EDIT:
開始インデックスは文字列である必要があります。

答えて

1

itertools.productをループしないようにするには、算術演算(ベース26)を自分で行う必要があります。しかし、少なくともx=len(self.startIndex) or 1を設定することができます!

0

古い(間違った)解答

あなたは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数トランスレータを使用(それは完璧に動作しませんでしたので、に基づいて(とfixxedを):http://quora.com/How-do-I-write-a-program-in-Python-that-can-convert-an-integer-from-one-base-to-another

I 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) 
+0

申し訳ありませんが、それは不明であったが、私は開始インデックスが文字列であることが予想場合。また、インデックスが25を超える場合、それは動作しないようです。最後に、「AZ」の後に、「BA」の代わりに「ABA」が得られます。 – UKDP

+0

申し訳ありませんが、あなたをよく理解していませんでした。問題を考えると、再帰的なジェネレータのようなものが必要かもしれないと思うので、本質的に無限の深さのツリー構造をループしているからです。 – Yorian

+0

ありがとうございます。それでもなお別の問題があります。私が "AAZ"の後のインデックスから始めると、私は無限ループに陥ります。 – UKDP

関連する問題