企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 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 ``` 它非常难懂,而且优化也不明显。这值得吗?我希望你有很好的见解。性能并不是一切。你在优化方面的努力应该与程序的可读性和可维护性相平衡。