晚上翻手機(jī),看見一道網(wǎng)友發(fā)的python面試題求助帖,當(dāng)時(shí)簡(jiǎn)單掃一眼就跳過了,但下來仔細(xì)想想覺得還蠻有趣,開電腦梳理下思路,因?yàn)闆]有官方答案,所以大家可以一起來做做,其中涉及的python知識(shí)點(diǎn)還是蠻多的。
題目?jī)?nèi)容
一個(gè)標(biāo)準(zhǔn)的版本需要涵蓋,大版本.小版本.補(bǔ)丁版,各版本之間使用英文點(diǎn)符號(hào)分隔,且每個(gè)版本取值范圍均為0~99。
現(xiàn)有一批產(chǎn)品版本號(hào)列表,需要過濾掉不符合要求的內(nèi)容后,將版本號(hào)通過sorted進(jìn)行升序排列。
題目分析
初看此題,給人的感覺有些好笑,居然要告訴大家使用sorted進(jìn)行排序,難道是生怕誰不知道這個(gè)函數(shù)嗎?
但當(dāng)隨便驗(yàn)證兩個(gè)用例發(fā)現(xiàn),sorted的默認(rèn)排序存在BUG。
sorted(['1.3.0','1.1.0','1.2.0'])
>>> ['1.1.0', '1.2.0', '1.3.0']
# 錯(cuò)誤的默認(rèn)排序
sorted(['1.30.0','1.4.0','1.2.0'])
>>> ['1.2.0', '1.30.0', '1.4.0']
直接使用字符串進(jìn)行排序,默認(rèn)是按位對(duì)比每個(gè)版本號(hào),然后進(jìn)行排序,這導(dǎo)致了1.30.0 < 1.4.0的BUG。
仔細(xì)想想,面試官想考察的應(yīng)該是sorted的自定義排序方法。那么該如何正確的比較所有版本號(hào),又能同時(shí)過濾掉錯(cuò)誤的版本號(hào)呢?
過濾版本號(hào)
考慮到版本號(hào)的特殊性,最簡(jiǎn)單的過濾方法,必然是正則了:
import re
pattern = re.compile(r'^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}')
if not pattern.match(version):
raise ValueError("error version [%s],the version type must be [xx.xx.xx]" % version)
當(dāng)然這里是我們驗(yàn)證的操作方式,排序時(shí)當(dāng)然不能拋出異常了。
版本號(hào)比較
既然每個(gè)版本號(hào)的取值范圍在0-99之間,那么熟悉數(shù)學(xué)的我們,是否有了思路?我們按照百進(jìn)制的方式,來統(tǒng)計(jì)版本號(hào),不就能輕易的達(dá)到目的么?就拿剛才的1.30.0和1.4.0來舉例如下:
| 版本號(hào) | 大版本(10000) | 小版本(100) | 補(bǔ)丁版本(1) | 總計(jì) |
|---|---|---|---|---|
| 1.30.0 | 10000 | 3000 | 0 | 13000 |
| 1.4.0 | 10000 | 400 | 0 | 10400 |
| 2.1.0 | 20000 | 100 | 0 | 20100 |
最終代碼
# -*- coding: utf-8 -*-
# @微信號(hào) : King_Uranus
# @公眾號(hào) : 清風(fēng)Python
# @GitHub : https://github.com/BreezePython
# @Date : 2020/11/04 22:48:33
# @Software : PyCharm
# @version :Python 3.7.8
# @File : compare_version.py
import re
class CompareVersion:
def __init__(self, version_list):
self.versions = version_list
self.error_version_num = 0
def com_version(self, version):
sum_version = 0
version_weights = [10000, 100, 1]
pattern = re.compile(r'^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}')
if not pattern.match(version):
self.error_version_num += 1
return -1
version_list = version.split('.')
for index, small_version in enumerate(version_list):
sum_version += version_weights[index] * int(small_version)
return sum_version
def sort_version(self):
sorted_version = sorted(self.versions, key=lambda x: self.com_version(x))
return sorted_version[self.error_version_num:]
if __name__ == '__main__':
versions = ['0.0.0', '99.99.99', '100.0.1', '1.0.-1', '1.1.99',
'2.10.1', '2.9.10', '999', '10-0.1']
main_class = CompareVersion(versions)
print(main_class.sort_version())
output:
['0.0.0', '1.1.99', '2.9.10', '2.10.1', '99.99.99']
在sorted遍歷過程中,每當(dāng)發(fā)現(xiàn)一個(gè)錯(cuò)誤版本號(hào),我們就將error_version_num加一,并返回-1,這樣當(dāng)最終排序后,將切片的排序結(jié)果返回,就達(dá)到了最終的目的。
當(dāng)然了,這只是我一時(shí)興起的拋磚引玉答案,期待大家給出更好的作答。
The End
期待你關(guān)注我的公眾號(hào)清風(fēng)Python,如果你覺得不錯(cuò),希望能動(dòng)動(dòng)手指轉(zhuǎn)發(fā)給你身邊的朋友們。
我的github地址:https://github.com/BreezePython