5

我已经查看了其他几个与此“相似”的 SO 问题(以及谷歌搜索的大量问题),但它们似乎都不适合我的问题。

我正在尝试制作一个非固定长度的唯一文本字符串,仅包含我指定的字符串中的字符。例如,由大写和小写的 a-zA-Z 字符组成。(对于这个例子,我只使用 a、b 和 c 小写字母)

像这样的东西(下面的破代码)

def next(index, validCharacters = 'abc'):
    return uniqueShortAsPossibleString

index 参数将是与文本字符串相关的索引(整数),例如:

next(1)  == 'a'
next(2)  == 'b'
next(3)  == 'c'

next(4)  == 'aa'
next(5)  == 'ab'
next(6)  == 'ac'

next(7)  == 'ba'
next(8)  == 'bb'
next(9)  == 'bc'

next(10) == 'ca'
next(11) == 'cb'
next(12) == 'cc'

等等。字符串:

  1. 必须是唯一的,我将使用它作为标识符,它只能是 a-zA-Z 字符
  2. 尽可能短,较低的索引号最短(参见上面的示例)
  3. 仅包含给定参数字符串 validCharacters 中指定的字符

总之,我如何编写 next() 函数来将整数索引值与指定字符的唯一短字符串相关联?

PS我是新手,这个网站多年来帮助了我很多,虽然我从来没有注册过或问过问题(直到现在),但我真的希望我在解释我的工作方面做得很好我试图做到这一点。

4

6 回答 6

3

您要做的是将next函数的参数写入另一个库中。

假设validCharacters包含k字符:那么next函数p的工作就是k使用validCharacters.

在您的示例中,您可以以 3 为基数编写数字,然后将每个数字与一个字母相关联:

next(1) -> 1 -> 'a'
next(2) -> 2 -> 'b'

next(4) -> 11 -> 'aa'
next(7) -> 21 -> 'ba'

等等。

使用此方法,您可以next(x)在不知道或计算 any的情况下调用next(x-i),这是迭代方法无法做到的。

于 2012-10-25T06:36:50.680 回答
1

itertools总是可以给你混淆的单线迭代器:

from itertools import combinations_with_replacement, chain

chars = 'abc'
a = chain(*(combinations_with_replacement(chars, i) for i in range(1, len(chars) + 1)))

基本上,这段代码创建了一个迭代器,它结合了所有chars长度的组合12...,len(chars)

的输出for x in a: print x是:

('a',)
('b',)
('c',)
('a', 'b')
('a', 'c')
('b', 'a')
('b', 'c')
('c', 'a')
('c', 'b')
('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a')
于 2012-10-25T06:35:27.923 回答
1

您不能真正将索引与烦人“关联”,但以下是一个生成器,它将产生并提供您要求的输出:

from itertools import combinations_with_replacement

def uniquenames(chars):
    for i in range(1, len(chars)):
        for j in combinations_with_replacement(chars, i):
            yield ''.join(j)

print list(uniquenames('abc'))
# ['a', 'b', 'c', 'aa', 'ab', 'ac', 'bb', 'bc', 'cc']
于 2012-10-25T06:35:37.330 回答
1

据我了解,我们不应该指定输出字符串的最大长度。所以range还不够:

>>> from itertools import combinations_with_replacement, count
>>> def u(chars):
...     for i in count(1):
...         for k in combinations_with_replacement(chars, i):
...             yield "".join(k)
... 
>>> g = u("abc")
>>> next(g)
'a'
>>> next(g)
'b'
>>> next(g)
'c'
>>> next(g)
'aa'
>>> next(g)
'ab'
>>> next(g)
'ac'
>>> next(g)
'bb'
>>> next(g)
'bc'
于 2012-10-25T06:44:27.633 回答
1

您正在尝试将数字转换为另一个基数中的数字,但使用任意字符作为该基数的数字。

import string
chars = string.lowercase + string.uppercase

def identifier(x, chars):
    output = []
    base = len(chars)
    while x:
        output.append(chars[x % base])
        x /= base
    return ''.join(reversed(output))

print identifier(1, chars)

这使您可以跳转到任何位置,您正在计数,因此标识符是完全唯一的,并且很容易使用任何长度(两个或更多)的任何字符集,并且较低的数字给出较短的标识符。

于 2012-10-25T06:45:43.850 回答
0

因此,您似乎正在尝试枚举语言 {'a','b','c'} 生成的所有字符串。这可以使用有限状态自动机来完成(尽管您不想这样做)。枚举语言的一种简单方法是从一个列表开始,并按顺序附加所有长度为 1 的字符串(所以 a 然后 b 然后 c)。然后将字母表中的每个字母附加到每个长度为 n-1 的字符串中。只要您将字母表中的所有字母附加到给定的字符串,然后再转到按字典顺序排列的下一个字符串,它就会保持有序。

于 2012-10-25T06:37:17.530 回答