纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Python之有限状态机识别地址 Python编程使用有限状态机识别地址有效性

somenzz   2021-09-14 我要评论
想了解Python编程使用有限状态机识别地址有效性的相关内容吗somenzz在本文为您仔细讲解Python之有限状态机识别地址的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Python编程,Python状态机,有限状态机识别地址有效性下面大家一起来学习吧

在收发快递填写地址的时候我们会经常手动输入地址让程序智能识别标准的地址比如xx省xx市xx县/区xx路xx号不过有时候也可以简单写:xx市xx县/区xx路xx号或者xx省xx县/区xx路xx号或者xx市xx路xx号

但是有些就不是合法的地址了比如 xx省xx街道xx号或者 xx市xx省xx区xx号

那么问题来了如何识别一个地址是否有效确切的讲如何编程识别一个中国地址是否有效?

虽然我们大脑可以一眼识别但是让计算器去识别可以不是一件容易的事根本原因在于地址的描述虽然看上去简单但是它依然是比较复杂的上下文有关的文法

比如 “上海市北京东路 xx 号南京市北京东路 xx 号”扫描到北京东路时它后面的门牌号是否构成正确的地址要看上下文即城市名

所幸的是地址的上下文比较简单是有限的虽然我们可以暴力穷举所有省、市、区、街道但有效的方法还是有限状态机

每一个有限状态机都有一个开始状态和一个终止状态以及若干中间状态每一条弧上带着一个状态进入下一个状态的条件比如在上图中当前的状态如果是省如果遇到下一个词组和区有关就进入区如果遇到下一个词组和城市有关那么就进入市

如果一条地址能从状态机的开始状态经过状态机的若干中间状态最终走到终止状态则这条地址有效否则无效

比如 xx市xx省xx区xx号 就是无效地址无法从市走到省

现在我们通过一个简单的优先状态机来实现代码有注释很容易看懂

from enum import Enum
def isAddress(address: str) -> bool:
 
    #定义状态
    State = Enum("State", [
        "STATE_INITIAL", #开始
        "STATE_PROVINCE", # 省
        "STATE_CITY", # 市
        "STATE_AREA", # 区 / 县
        "STATE_STREET", # 街道
        "STATE_NUM", #号
        "STATE_END", #结束
        "STATE_ILLEGAL", #错误状态
    ])
    def toAddressType(addr_slice : str) -> State:
        if "省" in addr_slice:
            return State.STATE_PROVINCE
        elif "市" in addr_slice:
            return State.STATE_CITY
        elif "区" in addr_slice or "县" in addr_slice:
            return State.STATE_AREA
        elif "路" in addr_slice or "街道" in addr_slice:
            return State.STATE_STREET
        elif "号" in addr_slice:
            return State.STATE_NUM
        else:
            return State.STATE_ILLEGAL   
    #定义状态转移   
    transfer = {
        #开始可以转为 省或市
        State.STATE_INITIAL: {
            State.STATE_PROVINCE, 
            State.STATE_CITY,
        },
        #省可以转 市或区县
        State.STATE_PROVINCE:{
            State.STATE_CITY,
            State.STATE_AREA,
        },
        #市可以转区或街道
        State.STATE_CITY: {
            State.STATE_AREA,
            State.STATE_STREET,
        },
        #区县可以转街道
        State.STATE_AREA: {
            State.STATE_STREET,
        },
        #街道可以转号或终止
        State.STATE_STREET: {
            State.STATE_NUM,
            State.STATE_END,
        },
        #号只能转终止
        State.STATE_NUM: {
            State.STATE_END,
        },
    } 
    st = State.STATE_INITIAL
    for ch in address:
        current_state = toAddressType(ch)
        if current_state not in transfer[st]:
            return False
        st = current_state 
     return st in [State.STATE_STREET, State.STATE_NUM,State.STATE_END] 
if __name__ == '__main__':
    address1 = ["江苏省","苏州市", "吴中区", "中山北路", "208号"]
    address2 = ["苏州市","吴中区", "中山北路", "208号"]
    address3 = ["苏州市","吴江区", "中山北路", "208号"]
    address4 = ["苏州市","吴江区","208号"]
    address5 = ["苏州市","中山北路"]
    assert isAddress(address1)
    assert isAddress(address2)
    assert isAddress(address3)
    assert isAddress(address5)
    assert isAddress(address4) == False
 

这里没有对整个地址字符串进行分词而是直接将地址写成了列表的形式主要为了说明状态机的实现和应用上述代码仅能从格式上保证地址是有效的并不能确保地址真实有效如果要判断是真实有效的那就需要将全国所有的省、市、区县、街道建立一个 hash 表门牌号可以用范围表示再进行状态转移判断

上述代码的 transfer 就是一个 hash 表相当于把所有正确转移的情况都穷举了一遍它穷尽了在任何一种情况下对应任何的输入需要转义的状态

最后的话

本文分享了如何实现一个简单的有限状态机

附有限状态机的开源实现:

django-fsm[1]

python-state-machine[2]

参考资料

[1]

django-fsm:

https://github.com/viewflow/django-fsm

[2]

python-state-machine:

 https://github.com/jtushman/state_machine


相关文章

猜您喜欢

  • Vuex总体 Vuex总体案例详解

    想了解Vuex总体案例详解的相关内容吗猫老板的豆在本文为您仔细讲解Vuex总体的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Vuex详解,Vuex总结详解下面大家一起来学习吧..
  • Python并发编程队列与多线程 Python并发编程队列与多线程最快发送http请求方式

    想了解Python并发编程队列与多线程最快发送http请求方式的相关内容吗somenzz在本文为您仔细讲解Python并发编程队列与多线程的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Python并发编程,Python多线程,Python队列下面大家一起来学习吧..

网友评论

Copyright 2020 www.sopisoft.net 【绿软下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式