晚上翻手机,看见一道网友发的python面试题求助帖,当时简单扫一眼就跳过了,但下来仔细想想觉得还蛮有趣,开电脑梳理下思路,因为没有官方答案,所以大家可以一起来做做,其中涉及的python知识点还是蛮多的。
题目内容
一个标准的版本需要涵盖,大版本.小版本.补丁版,各版本之间使用英文点符号分隔,且每个版本取值范围均为0~99。
现有一批产品版本号列表,需要过滤掉不符合要求的内容后,将版本号通过sorted进行升序排列。
题目分析
初看此题,给人的感觉有些好笑,居然要告诉大家使用sorted进行排序,难道是生怕谁不知道这个函数吗?
但当随便验证两个用例发现,sorted的默认排序存在BUG。
sorted(['1.3.0','1.1.0','1.2.0'])
>>> ['1.1.0', '1.2.0', '1.3.0']
# 错误的默认排序
sorted(['1.30.0','1.4.0','1.2.0'])
>>> ['1.2.0', '1.30.0', '1.4.0']
直接使用字符串进行排序,默认是按位对比每个版本号,然后进行排序,这导致了1.30.0 < 1.4.0的BUG。
仔细想想,面试官想考察的应该是sorted的自定义排序方法。那么该如何正确的比较所有版本号,又能同时过滤掉错误的版本号呢?
过滤版本号
考虑到版本号的特殊性,最简单的过滤方法,必然是正则了:
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)
当然这里是我们验证的操作方式,排序时当然不能抛出异常了。
版本号比较
既然每个版本号的取值范围在0-99之间,那么熟悉数学的我们,是否有了思路?我们按照百进制的方式,来统计版本号,不就能轻易的达到目的么?就拿刚才的1.30.0和1.4.0来举例如下:
版本号 | 大版本(10000) | 小版本(100) | 补丁版本(1) | 总计 |
---|---|---|---|---|
1.30.0 | 10000 | 3000 | 0 | 13000 |
1.4.0 | 10000 | 400 | 0 | 10400 |
2.1.0 | 20000 | 100 | 0 | 20100 |
最终代码
# -*- coding: utf-8 -*-
# @微信号 : King_Uranus
# @公众号 : 清风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遍历过程中,每当发现一个错误版本号,我们就将error_version_num加一,并返回-1,这样当最终排序后,将切片的排序结果返回,就达到了最终的目的。
当然了,这只是我一时兴起的抛砖引玉答案,期待大家给出更好的作答。
The End
期待你关注我的公众号清风Python
,如果你觉得不错,希望能动动手指转发给你身边的朋友们。
我的github地址:https://github.com/BreezePython