18.6. 优化字符串操作
18.6. 优化字符串操作
Soundex 算法的最后一步是对短结果补零和截短长结果。最佳的做法是什么?
这是目前在 soundex/stage2/soundex2c.py 中的做法:
digits3 = re.sub('9', '', digits2) while len(digits3) < 4: digits3 += "0" return digits3[:4]
这里是 soundex2c.py 的表现:
C:\samples\soundex\stage2>python soundex2c.py Woo W000 12.6070768771 Pilgrim P426 14.4033353401 Flingjingwaller F452 19.7774882003
思考的第一件事是以循环取代正则表达式。这里的代码来自 soundex/stage4/soundex4a.py:
digits3 = '' for d in digits2: if d != '9': digits3 += d
soundex4a.py 快了吗?是的:
C:\samples\soundex\stage4>python soundex4a.py Woo W000 6.62865531792 Pilgrim P426 9.02247576158 Flingjingwaller F452 13.6328416042
但是,等一下。 一个从字符串去除字符的循环? 我们可以用一个简单的字符串方法做到。这便是 soundex/stage4/soundex4b.py:
digits3 = digits2.replace('9', '')
soundex4b.py 快了吗?这是个有趣的问题,它取决输入值:
C:\samples\soundex\stage4>python soundex4b.py Woo W000 6.75477414029 Pilgrim P426 7.56652144337 Flingjingwaller F452 10.8727729362
soundex4b.py 中的字符串方法对于大多数名字比循环快,但是对于短小的情况(很短的名字)却比 soundex4a.py 略微慢些。 性能优化并不总是一致的,对于一个情况快些,却可能对另外一些情况慢些。 就此而言,大多数情况将会从改变中获益,所以就改吧,但是别忘了原则。
最后仍很重要的是,让我们检测算法的最后两步:以零补齐短结果和截短超过四字符的长结果。你在 soundex4b.py 中看到的代码就是做这个工作的,但是太没效率了。看一下 soundex/stage4/soundex4c.py 找出原因:
digits3 += '000' return digits3[:4]
我们为什么需要一个 while 循环来补齐结果? 我们早就知道我们需要把结果截成四字符,并且我们知道我们已经有了一个没有改变的字符(起始字符从 source 中不作改变的拿过来)。 这意味着我们可以仅仅在输出的结尾添加三个零,然后截短它。 不要害怕重新理解问题,从不太一样的角度看问题可以获得简单的解决方案。
我们丢弃 while 循环后从 soundex4c.py 中获得怎样的速度? 太明显了:
C:\samples\soundex\stage4>python soundex4c.py Woo W000 4.89129791636 Pilgrim P426 7.30642134685 Flingjingwaller F452 10.689832367
最后,还有一件事可以另这三行运行的更快:你可以把它们合并为一行。 看一眼 soundex/stage4/soundex4d.py:
return (digits2.replace('9', '') + '000')[:4]
在 soundex4d.py 中把所有代码放在一行可以比 soundex4c.py 稍微快那么一点:
C:\samples\soundex\stage4>python soundex4d.py Woo W000 4.93624105857 Pilgrim P426 7.19747593619 Flingjingwaller F452 10.5490700634
它非常难懂,而且优化也不明显。 这值得吗? 我希望你有很好的见解。 性能并不是一切。 你在优化方面的努力应该与程序的可读性和可维护性相平衡。