我有一个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.我已经知道我可以用globals替换"state"变量(yuck!)或者可能将它们作为属性附加到函数中,但这些都不是特别优雅.
此外,Python没有类似Perl的魔法自动增量,如果你"++"是一个值为"A"的变量,它变为"B" - 或者如果它是"Z",它就变成"AA".所以这也是一个曲线球.
我是一个黑客攻击解决方案,但它真的很丑,难以阅读.从Perl到Python的翻译应该会产生相反的效果,对吧?:)所以我将此作为对SO用户的挑战.你能把它变成一个优雅的Python函数吗?
请查看此答案,了解将数字转换为字母数字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
好吧,很遗憾地说,但你不能只是直接从Perl转换到Python(包括逐位Perlisms)并期望结果更漂亮.它不会,它会更加丑陋.
如果你想要Python的美味,你需要使用Python习语.
现在提出问题:
from string import uppercase class Uniquifier(object): def __init__(self): self.last_timestamp = None self.last_suffix = 0 def uniquify(self, timestamp): if timestamp == self.last_timestamp: timestamp = '%s%s' % (timestamp, uppercase[self.last_suffix]) self.last_suffix += 1 else: self.last_suffix = 0 self.timestamp = timestamp return timestamp uniquifier = Uniquifier() uniquifier.uniquify(a_timestamp)
更漂亮?也许.更具可读性?大概.
编辑(重新评论):是的,这在Z之后失败了,我对这个解决方案完全不满意.所以我不会解决它,但可能提供更好的东西,比如使用数字:
timestamp = '%s%s' % (timestamp, self.last_suffix)
如果是我,我会这样做:
import uuid def uniquify(timestamp): return '%s-%s' % (timestamp, uuid.uuid4())
只是快乐.