第一次个人编程作业
点击访问GitHub: https://github.com/Schicksal-zzq
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 150 | 180 |
Analysis | 需求分析(包括学习新技术) | 75 | 70 |
Design Spec | 生成设计文档 | 10 | 20 |
Design Review | 设计复审 | 35 | 40 |
Coding Standard | 代码规范(为开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 100 | 120 |
Coding | 具体编码 | 300 | 250 |
Code Review | 代码复审 | 60 | 30 |
Test | 测试(自我测试,修改,提交修改) | 100 | 120 |
Reporting | 报告 | 60 | 60 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结并提出过程改进计划 | 35 | 40 |
合计 | 1025 | 1030 |
程序设计及实现过程
先看输入字符串的特点
-
每行一个输入数据,带有前缀x!,其中x表示难度级别,且每行末尾有英文句号
-
省/市级行政区如后缀为“省”/“市”,则有可能省略后缀
-
若县级行政区后缀为“县”,则可能缺失整个市级行政区
-
除第3条情况外,省市级行政区不会缺失
-
县/乡级行政区可能缺失,且整个地址一定从大到小顺序
设计过程
-
其中名字一定在字符串前面且有逗号隔开,故先将名字切割出来
-
题目中的手机号一定是连续且长度为11,可以轻松找到
-
然后开始慢慢切割地址,但因为四个直辖市的特殊存在,我把这步操作分两种情况
- 一种是将四个直辖市单独进行检查,且找到这城市以后直接当成城市,再分割前两个字当省份
- 另一种是把剩下的省份/自治区/特别行政区等统一考虑,但是!又由于可能缺省的情况,我选择打表
-
最后根据等级,再做相应的操作
实现过程
本程序共创建了一个类,三个方法如下
类名 | 方法 | 功能 |
---|---|---|
AddrInfo | get_name() | 获取名字 |
get_tele() | 获取手机号 | |
get_addr() | 获取地址 |
主要代码量是在get_addr()中,也是这个类的核心方法,函数先把最后一个英文句号去掉然后再开始处理子串。
1.先是处理四个直辖市的特殊情况: 太过丑陋,建议跳过
my_addr = re.search("(^北京|^上海|^重庆|^天津)([市]?)(([^0-9]{0,4}?区|[^0-9]{0,4}?县|[^0-9]{0,4}?市)?)(([^0-9]{0,4}?乡|[^0-9]{0,4}?镇|[^0-9]{0,6}?街道|[^0-9]{0,6}?区)?)((.{1,4}?巷|.{1,6}?路|.{1,6}?街|.{1,6}?道|.{1,6}?弄|.{1,6}?里|.{1,6}?寺|.{1,6}?东里|.{1,6}?胡同)?)((\d.*?号|\d.*?弄|甲\d.*?号)?)(.*)",procstr)
注意要控制长度,因为可能有一级缺省而行末有这些关键字导致子串全部被吞。
经过我一万亿次的修改长度,目前能避免大多数的误判。 其他我也没办法了,gou头保命
2.接下来处理其他省份自治区等情况:
这部分内容和上面处理大致一样。不要问我那省/市怎么办,别问,问就是暴力匹配。首先将所有省存在province中,然后再把所有市存在city中,经过处理,不管却不缺省都可以补全或者不补全。要注意的是,市级城市与自治州,地区,盟是同一等级的,但是我搜城市名单的时候没有这些东西。。
3.对于不同等级的处理方式:
一二等级可以合并,七级地址将后三个字符串连在一起就是五级地址了,对于三等级采用地理/逆地理编码,详情请点击访问高德:https://lbs.amap.com/api/webservice/guide/api/georegeo。
性能分析与改进
耗时部分主要在读取数据部分,可以通过open()函数来提高效率。而get_addr()部分仅占百分五左右,可以不用尽力优化。
单元测试
测试样例
# 1!司空款,宁夏回族自治区吴忠市13848197454青铜峡市瞿靖镇青黄公路尚桥村村委会.
# 2!祁东黄,广西壮族自治区梧州市岑13107532064溪市糯垌镇叶伦村卫生所.
# 2!穆拙箫,湖北省咸宁市咸安区咸15070735592安大道渡船新村超市.
# 2!戎菱怠,河南平顶山市新华区西市场街道平安大道红旗街小区16号楼13726321206.
# 2!祁绘,18829697666上海市杨浦区密云路422号.
# 1!幸晴,贵州省黔东南苗族侗族自治州岑巩县思13377199751旸镇磨寨村磨寨小学.
# 3!何振,黑龙江省大庆龙15691073609凤街道凤阳路283号炼厂居委会.
# 1!古鲜,新疆维吾尔自治区克孜勒苏柯尔克孜自治州阿图什市松他克乡光15282688499明路街道买谢提村民委员会中共买谢特村支部委员会.
# 1!卞宅喉,福建省福州台13358282648江区上海街道交通路17号交通花园5座.
# 1!满虏,河南省焦作15165434173市山阳区中星街道焦辉路中马村巧莲大型弹花.
部分代码
# Author: Administrator
# date: 2019/9/27 21:01
import unittest
from test import AddrInfo
class Test_addr_info(unittest.TestCase):
tttt = '1!苗责忿,上海市浦东新18661707208区川环南路1223弄妙龙小区.'
leve = tttt[0]
tttt = tttt[2:]
def name_function(self):
onecase = AddrInfo()
deaddr = examp.get_name(tttt, leve)
self.assertEqual(deaddr, '上海市浦东新18661707208区川环南路1223弄妙龙小区')
def tele_function(self):
examp = AddrInfo()
deaddr = examp.get_tele('上海市浦东新18661707208区川环南路1223弄妙龙小区', leve)
self.assertEqual(deaddr, '上海市浦东新区川环南路1223弄妙龙小区')
def addr_function(self):
examp = AddrInfo()
deaddr = examp.get_addr('上海市浦东新区川环南路1223弄妙龙小区', leve)
aaaaaaaaaa = ['上海', '上海市', '浦东新区', '', '川环南路1223弄妙龙小区']
self.assertEqual(deaddr, aaaaaaaaaa)
if __name__ == '__main__':
unittest.main()
弄文件啥的太麻烦,我就直接拿字符串进去检错了。。留下不学无术的眼泪
代码覆盖率
异常处理
- 没有名字的时候
try:
self.name = my_name.group(1)
procstr = my_name.group(2)
except AttributeError:
pass
#1!,北京18605763052市昌平区温泉花园A区9号楼.
- 没有手机号的时候
try:
self.tele = my_tele.group()
except AttributeError:
pass
#1!杜崔逐,安徽省黄山市徽州区呈坎镇容溪村卫生室.
- 还有没有选择难度,地址啥的就不一一列举了。。。
我累了,不想写
艰辛的历程
吐了吐了,啥都不会。 |