【问题标题】:Generate alphanumeric strings sequentially按顺序生成字母数字字符串
【发布时间】:2011-08-20 18:12:39
【问题描述】:

我正在尝试创建一个循环来生成和打印字符串,如下所示:

  1. 仅限字母数字字符:
  2. 0-9在A-Z之前,在a-z之前,
  3. 长度最多为 4 个字符。

所以,它会打印:

  1. 0-z 的所有字符串
  2. 然后从 00-zz
  3. 然后从 000-zzz
  4. 然后从 0000-zzzz

然后它就停止了。

【问题讨论】:

  • 您的问题太难理解了... a07z 是否是合法字符串?
  • 是的。所有长度为 1-4 的字母数字字符串都是合法的
  • 所以当你说 0-9 在 A-Z 之前是指 0000 应该在 A000 之前?

标签: python string algorithm


【解决方案1】:
from string import digits, ascii_uppercase, ascii_lowercase
from itertools import product

chars = digits + ascii_uppercase + ascii_lowercase

for n in range(1, 4 + 1):
    for comb in product(chars, repeat=n):
        print ''.join(comb)

这首先创建一个由所有数字、大写字母和小写字母组成的字符串。

然后,对于从 1 到 4 的每个长度,它会打印这些数字和字母的所有可能组合。

请记住,这是很多组合——62^4 + 62^3 + 62^2 + 62。

【讨论】:

  • 这是一个很酷的解决方案。还有一件很酷的事情是让它成为一个生成器,而不是直接打印字符串。
  • 我知道这是很多组合,我主要是为了测试目的。我把它减少到 3 个字符而不是 4 个
  • 是的,他说他想要一个“打印字符串的循环”,所以这就是我给他的。
  • 仅供参考ascii_lowercase + ascii_uppercase == ascii_letters
【解决方案2】:

我不喜欢在我之前使用product 给出的答案,因为在 python 文档中查看它的实现,它似乎在开始产生结果之前将整个事情跨越到内存中的一个列表中。

这对您的情况非常不利,因为正如 agf 自己所说,这里的排列数量很大(超过一百万)。对于这种情况,创建了 yield 语句 - 这样就可以动态生成巨大的列表,而不是跨越内存(我也不喜欢浪费的 range ,其中 xrange 完全适用)。

我会寻求这样的解决方案:

def generate(chars, length, prefix = None):
    if length < 1:
        return
    if not prefix:
        prefix = ''
    for char in chars:
        permutation = prefix + char
        if length == 1:
            yield permutation
        else:
            for sub_permutation in generate(chars, length - 1, prefix = permutation):
                yield sub_permutation

这样,内存中的所有内容都是深度为“n”的递归堆栈,其中“n”是排列的长度(在本例中为 4),并且每次只返回一个元素。

chars 是可供选择的字符集,长度为 4,用途与产品非常相似,只是它在运行时不会跨越内存中的整个列表。

【讨论】:

  • 它在product描述中说——“这个函数相当于下面的代码,只是实际实现不会在内存中建立中间结果:”@987654327中的所有工具@ 那样工作,这是模块的全部目的。
  • 我认为对于非常小的范围,range 实际上比xrange 浪费更少。
【解决方案3】:

我今天编写了这个代码。它完全符合您的要求以及更多。它也是可扩展的

def lastCase (lst):
    for i in range(0, len(lst)):
        if ( lst[i] != '_' ):
            return False
    return True


l = [''] * 4 #change size here if needed. I used 4
l[0] = '0'
index = 0

while ( not lastCase(l) ):

    if ( ord(l[index]) > ord('_') ):
        l[index] = '0'
        index += 1
        while( l[index] == '_' ):
            l[index] = '0'
            index += 1
        if (l[index] == ''):
            l[index] = '0'

    #print or process generated string
    print(''.join(l))

    l[index] = chr(ord(l[index]) +1)

    if ( ord(l[index]) > ord('9') and ord(l[index]) < ord('A') ):
        l[index] = 'A'
    elif ( ord(l[index]) > ord('Z') and ord(l[index]) < ord('_')  ): 
        l[index] = '_'

    index = 0

print (''.join(l))

【讨论】:

    【解决方案4】:
    from string import digits, ascii_uppercase, ascii_lowercase
    from itertools import product
    chars = digits + ascii_uppercase + ascii_lowercase
    
    def give_me_next(lst):
            lst = lst[::-1]
            change_next = False
            change = True
            n = 0
            for x in lst:
                    if change_next == True:
                            change_next = False
                            pos = chars.find(x)
                            try:
                                    a =  chars[pos+1]
                                    lst = list(lst)
                                    lst[n] = a
                                    lst = "".join(lst)
                                    x = a
                            except:
                                    lst = list(lst)
                                    lst[n] = '0'
                                    lst = "".join(lst)
                                    change_next = True
                                    x = '0'
    
                    pos = chars.find(x)
                    try:
                            a =  chars[pos+1]
                            if change == True:
                                    lst = list(lst)
                                    lst[n] = a
                                    lst = "".join(lst)
                                    change = False
                    except:
                            lst = list(lst)
                            lst[n] = '0'
                            lst = "".join(lst)
                            change_next = True
    
                    n = n + 1
    
            lst = lst[::-1]
            return lst
    
    a=  give_me_next('zzzzz')
    while True:
            a =  give_me_next(a)
            print a
    

    【讨论】:

      【解决方案5】:

      这对我来说似乎是最简单的解决方案:

      from string import digits, ascii_uppercase, ascii_lowercase
      
      chars = digits + ascii_uppercase + ascii_lowercase
      all_str = [''.join([a]) for a in chars] \
              + [''.join([a,b]) for a in chars for b in chars] \
              + [''.join([a,b,c]) for a in chars for b in chars for c in chars] \
              + [''.join([a,b,c,d]) for a in chars for b in chars for c in chars for d in chars]
      
      print(all_str)
      print("Number of strings:", len(all_str))
      

      Example for strings with maximum 2 characters.

      当然,可能有一种方法可以概括为每个字符串的最大字符数,但是由于您对最多 4 个字符的字符串有特定的需求,这很好。

      【讨论】:

        猜你喜欢
        • 2022-01-02
        • 2016-04-21
        • 1970-01-01
        • 1970-01-01
        • 2013-02-03
        • 1970-01-01
        • 2013-10-22
        • 1970-01-01
        相关资源
        最近更新 更多