我有一个Perl函数,它需要一个时间戳,并返回不变的时间戳(如果它以前从来没有看到),或者以其他方式附加一些字母,使其唯一:
sub uniqify($) { my $timestamp = shift; state $last_ts = -1; state $next_letter = 'A'; if ($timestamp == $last_ts) { $timestamp .= $next_letter++; } else { $last_ts = $timestamp; $next_letter = 'A'; } return $timestamp; }
所以如果你调用它四次,值为1,1,1和2,它将返回1,然后是1A,然后是1B,然后是2.
注意:它只会随着日益增长的时间戳而被呼叫,所以它不需要记住每一个人,只有最后一个.
现在我需要将这个函数转换成Python.我了解到,我可以用全局变量(yuck!)替换“state”变量,或者将它们附加到函数作为属性,但是这两个变量都不是特别优雅的.
此外,Python没有像Perl的魔法自动增量,如果你的“”值为“A”的变量,它变成“B”,或者如果是“Z”,它变成“AA”.所以这也是曲线球.
我正在一起解决一个问题,但这真的很难看,很难看.从Perl翻译成Python应该有相反的效果,对吧? :)所以我提供这是对SO用户的挑战.你能使它成为一个优雅的Python函数吗?
解决方法
看看
this answer for a robust method to convert a number to an alphanumeric id
我现在的代码不会从’Z’转到’AA’,而是转到’BA’,但我想这并不重要,它仍然产生一个唯一的id
from string import uppercase as up import itertools def to_base(q,alphabet): if q < 0: raise ValueError( "must supply a positive integer" ) l = len(alphabet) converted = [] while q != 0: q,r = divmod(q,l) converted.insert(0,alphabet[r]) return "".join(converted) or alphabet[0] class TimestampUniqifier( object ): def __init__(self): self.last = '' self.counter = itertools.count() def __call__( self,str ): if str == self.last: suf = self.counter.next() return str + to_base( suf,up ) else: self.last = str self.counter = itertools.count() return str timestamp_uniqify = TimestampUniqifier()
用法:
timestamp_uniqify('1') '1' timestamp_uniqify('1') '1A' timestamp_uniqify('1') '1B' timestamp_uniqify('1') '1C' timestamp_uniqify('2') '2' timestamp_uniqify('3') '3' timestamp_uniqify('3') '3A' timestamp_uniqify('3') '3B'
你可以称之为maaaany次,它仍然会产生好的结果:
for i in range(100): print timestamp_uniqify('4') 4 4A 4B 4C 4D 4E 4F 4G 4H 4I 4J 4K 4L 4M 4N 4O 4P 4Q 4R 4S 4T 4U 4V 4W 4X 4Y 4Z 4BA 4BB 4BC 4BD 4BE 4BF 4BG 4BH 4BI 4BJ 4BK 4BL 4BM 4BN 4BO 4BP 4BQ 4BR 4BS 4BT 4BU 4BV 4BW 4BX 4BY 4BZ 4CA 4CB 4CC 4CD 4CE 4CF 4CG 4CH 4CI 4CJ 4CK 4CL 4CM 4CN 4CO 4CP 4CQ 4CR 4CS 4CT 4CU 4CV 4CW 4CX 4CY 4CZ 4DA 4DB 4DC 4DD 4DE 4DF 4DG 4DH 4DI 4DJ 4DK 4DL 4DM 4DN 4DO 4DP 4DQ 4DR 4DS 4DT 4DU