• 第一次个人编程作业


    github仓库地址:
    http://github.com/suweihuan079243/031702436]

    PSP表格

    PSP2.1 | Personal Software Process Stages |预估耗时(分钟)|实际耗时(分钟)

    • | :-: | -:
      Planning |· 计划| 1440|1980|
      · Estimate | · 估计这个任务需要多少时间 |1440| 1980
      Development| · 开发| 600|1000|
      · Analysis|· 需求分析 (包括学习新技术)|180|180|
      · Design Spec | · 生成设计文档 | 1440||
      · Design Review|· 设计复审 |1440|
      · Coding Standard| · 代码规范 (为目前的开发制定合适的规范) |30 |30|
      · Design|· 具体设计 |120|180|
      · Coding|· 具体编码)|600||
      · Code Review |· 代码复审|60 ||
      · Test| · 测试(自我测试,修改代码,提交修改) |180|
      · Reporting|· 报告 | ||
      · Test Repor|· 测试报告|||
      · Size Measurement|· 计算工作量|||
      · Postmortem & Process Improvement Plan|· 事后总结, 并提出过程改进计划|60||
      · |· 合计|7560||

    # 预备知识学习 #

    1. JSON
    由于本次的输入输出需要使用到JSON,所以迫不得已去学习了一下,以下是我学习json的一些资源分享

    2.正则表达式

    需要利用正则表达式分割信息中的level、name、phoneNumber
    • 这是在知乎上看到的github上的一个超过2w星的正则表达式学习项目

    https://github.com/ziishaned/learn-regex

    • 一个在线测试正则表达式的平台

    https://regex101.com/

    解题过程

    本次编程作业的解题过程真的太难了(我太菜了),多亏我的一位热心同学全程给予我很多帮助,帮我配置gradle和教我git的使用(虽然我每次commit都是让他帮我弄),还有编程过程遇到的一些问题占用了他很多时间,非常感谢这位热心同学.

    思路

    1. 由于涉及到杂乱字符串信息的提取,所以想到用正则表达式分割。
    2. 题目要求里有部分地址缺失,有点难定义一个完整的正则式来处理所有情况,所以想到通过全国 地图信息(省市县镇)来进行匹配。该地图为一个json文件,每级地址(除最后详细地址)下都有一个数组包含其下辖地址,通过逐级匹配来分割信息。
    3. 调用高德地图api,可惜不会。

    设计实现过程

    主要类

    • 个人信息类Person
    • 地图信息类MapData
    • 分割信息工具类Trim
    • Province类
    • City类
    • County类
    • Town类
    • Street类

    主要函数 # :

    • MapData.readMap():读取地图信息
    • void Trim.setNewInformation(String information):读取个人信息
    • void Trim.trimPhoneNumber():分割电话
    • void Trim.trimLevel():分割等级和姓名
    • void Trim.trimProvince():分割省份
    • void Trim.trimCity(Province province):分割城市
    • void Trim.trimCounty(City city):分割县级地区
    • void Trim.trimTown(County county):分割镇级地区
    • void Trim.trimStreet():分割镇以下地区
    • String Trim.trimInformation:去掉比较过的信息并返回新的信息

    关键代码

    public void trimProvince() {
    try {				
    MapData.readMap();
    } catch (IOException e) {
    e.printStackTrace();
    }
    person.setName(this.personName);//初始化姓名
    person.setPhoneNumber(this.phoneNumber);//初始化手机
    // 福建福州市鼓楼区鼓西街道湖滨路110号湖滨大厦一层.
    String provinceInformation = this.newInformation.substring(0, 2);//福建
    
    String provinceName =null;
    
    for (Province province : MapData.getProvinces()) {
       provinceName = province.getProvinceName().substring(0, 2);//福建
    if (provinceInformation.equals(provinceName)) {
    
    if (provinceName.equals("北京") || provinceName.equals("重庆") ||
    provinceName.equals("天津") ||provinceName.equals("上海")){
    //
    person.setProvince(province.getProvinceName());
    } else {
    person.setProvince(province.getProvinceName());
    this.newInformation = trimInformation(this.newInformation, province.getProvinceName());
    }
    this.province=province;
    break;
    }
    }
    if(this.province!=null){
    trimCity(this.province);
    }else {
    person.setProvince("""");
    }
    }
    
    1. 分割省份:先读取整个地图数据,截取信息的前两位用于省份匹配,遍历地图数据的省份,将provinceName与真实省名比较,如果相同则将信息与省名相同的部分去掉返回新的信息,并设置个人的省份,(ps:如果为直辖市,则只设置省份信息,方便后续用于城市信息的匹配),然后继续匹配城市。

       if(this.city!=null){
         trimCounty(this.city);
       }else{
        person.setCity("""");
       if(this.province!=null){
        List<City> cityList = this.province.getCities();
        for(City city:cityList){
        trimCounty(city);
        }	 } }
      
    2. 由于城市以下的地址可能为空,所以匹配完进行判断。如果不为空继续判断,否则通过去遍历此
      省份的所有城市去匹配其下辖的县级地区,后面类似。

       private void trimStreet() {
       if (this.level == 1) {
       person.setRestAddress(this.newInformation);//五级地址直接将镇以下赋值
       } else if (this.level == 2 || level == 3) {
       String regex1 = "(\D+)(\d+号)";//匹配路名和门牌号
       Pattern pattern = Pattern.compile(regex1);
       Matcher matcher = pattern.matcher(newInformation);
       String restAddress = null;
       if (matcher.find()) {
       restAddress = matcher.replaceFirst("");
       this.newInformation = matcher.group();
       String regex2 = "\d+号";
       String gateNumber = null;
       String roadName = null;
       Pattern pattern1 = Pattern.compile(regex2);
       Matcher matcher1 = pattern1.matcher(this.newInformation);
       if (matcher1.find()) {
       gateNumber = matcher1.group(0);//匹配门牌号
       roadName = matcher1.replaceAll("");//匹配路名
       }
       if(roadName!=null){
       person.setRoadName(roadName);
       }else {
       person.setRoadName("""");
       }
       if(gateNumber!=null){
       person.setGateNumber(gateNumber);
       }else{
       person.setGateNumber("""");
       }
       if(restAddress!=null){
       person.setRestAddress(restAddress);
       }else{
       person.setRestAddress("""");
       }
       }
       }
      
    3. 根据等级处理镇以下的地址信息,如果level=1,直接将镇以下的地址信息全部输出;如果是level2&level3,就继续利用正则分割为路、门牌号、详细地址(虽然我不知道是不是所有例子的门牌号都是以号结尾)

    性能分析


    说真的我看不懂更别说改进了,能有结果就不错了

    异常处理说明

    @Test
    public void testTrimLevel(){
        Trim trim=new Trim();
        trim.setNewInformation("1!宗衬缝,湖南省长沙市浏阳市古港镇024乡道古港镇梅田湖村村民委员15590409121会.");
        trim.trimLevel();
        System.out.println(trim.getLevel());
    }
    
    public void trimLevel() {
    
        String regexLevel = "[!,]";
    
        String[] split = this.newInformation.split(regexLevel);
    
        this.level = split[0];
    
        personName = split[1];
    
        this.newInformation = split[2];
        person.setName(this.personName);
    }
    

    一开始level定义为int类型,截取后通过Integer.parseInt()转为int类型,后面改来改去不知道为什么就会出现NumberformatException,找了半天找不到原因。就只好level定义为String类型就好了。

    	try {
            MapData.readMap();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String provinceInformation = this.newInformation.substring(0, 2);
        List<Province> provinceList = MapData.getProvinces();
        **for (Province province : provinceList) **
    

    一开始每级的分割地址*号部分经常出现nullpointerexception,原因是忘了先读取地图。

    大概就是这样,写了将近两天才勉强可以匹配部分情况,评测同学有点耐心将就着看吧。通过这次和以前完全不一样的作业,发现大佬们平时做的事情是真的牛批,天天群里都是99+说一些自己根本看不懂的东西,发现自己要学的东西还有很多,然后还有结对编程要做,浑身疼,洗洗睡了。

  • 相关阅读:
    164 Maximum Gap 最大间距
    162 Find Peak Element 寻找峰值
    160 Intersection of Two Linked Lists 相交链表
    155 Min Stack 最小栈
    154 Find Minimum in Rotated Sorted Array II
    153 Find Minimum in Rotated Sorted Array 旋转数组的最小值
    152 Maximum Product Subarray 乘积最大子序列
    151 Reverse Words in a String 翻转字符串里的单词
    bzoj3994: [SDOI2015]约数个数和
    bzoj 4590: [Shoi2015]自动刷题机
  • 原文地址:https://www.cnblogs.com/swh1148318751/p/11537575.html
Copyright © 2020-2023  润新知