问题描述
我有一个 Perl 函数,它接受一个时间戳并返回未更改的时间戳(如果它以前从未见过)或以其他方式附加一些字母以使其唯一:
I've got a Perl function which takes a timestamp and returns either the unchanged timestamp (if it's never seen it before) or otherwise, it appends some letters to make it unique:
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.
So if you call it four times, with the values 1, 1, 1, and 2, it will return 1, then 1A, then 1B, then 2.
注意:它只会在时间戳不断增加的情况下被调用,所以它不需要回忆它见过的每一个,只需要回忆最后一个.
Note: It only ever gets called with ever-increasing timestamps, so it doesn't need to recall every one it's ever seen, just the last one.
现在我需要将此函数转换为 Python.我了解到我可以用全局变量替换状态"变量(糟糕!),或者将它们作为属性附加到函数中,但这两种方法都不是特别优雅.
Now I need to translate this function to Python. I've learned that I can replace the "state" variables with globals (yuck!) or perhaps attach them to the function as attributes, but neither of those is particularly elegant.
此外,Python 没有像 Perl 的魔法自动增量那样的东西,如果你++"一个值为A"的变量,它会变成B"——或者如果它是Z",它会变成AA"".所以这也是一个曲线球.
Also, Python doesn't have something like Perl's magic autoincrement, where if you "++" a variable whose value is "A", it becomes "B" -- or if it's "Z", it becomes "AA". So that's a curveball too.
我正在拼凑一个解决方案,但它真的很难看且难以阅读.从 Perl 转换到 Python 应该会产生相反的效果,对吧?:) 因此,我将此作为对 SO 用户的挑战.你能把它变成一个优雅的 Python 函数吗?
I'm hacking together a solution, but it's really ugly and hard to read. Translating from Perl to Python is supposed to have the opposite effect, right? :) So I'm offering this as a challenge to SO users. Can you make it an elegant Python function?
推荐答案
我提供的代码不是从Z"变为AA",而是变为BA",但我认为这无关紧要,它仍然会产生唯一的 id
The code I present doesn't go from 'Z' to 'AA', instead goes to 'BA', but I suppose that doesn't matter, it still produces a unique 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'
你可以多次调用它,它仍然会产生很好的结果:
You can call it maaaany times and it will still produce good results:
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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!