博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python提取隐含结构的字符串
阅读量:4448 次
发布时间:2019-06-07

本文共 6847 字,大约阅读时间需要 22 分钟。

  当我用和(NLP的python调用工具)进行句法分析时,遇到一个很讨人厌的事情。

"(ROOT (IP (ADVP (AD \u4f46)) (NP (NN \u52a0\u5de5\u5382)) (VP (ADVP (AD \u8fd8\u662f)) (VP (VV \u7ee7\u7eed) (VP (VP (VV \u71c3\u70e7) (NP (NN \u80f6) (NN \u5236\u54c1))) (VP (VV \u6392\u653e) (NP (NN \u5e9f\u6c14)))))) (PU \u3002)))"

 

  句法分析结果如上述所示,但是并没有相关的python包能提供像这样的把一个字符串里面包括层次结果的数据结构化。(好吧,是我了解不深,如果您有的话,请一定要告诉我)我所说的结构化的意思是把上述字符串转换成json结构,方便继续分析。

[{u'IP  2': [{u'ADVP  3': u'AD \u4f46 4'},             {u'NP  5': u'NN \u52a0\u5de5\u5382 6'},             {u'VP  7': [{u'ADVP  8': u'AD \u8fd8\u662f 9'},                         {u'VP  10': [u'VV \u7ee7\u7eed 11',                                      {u'VP  12': [{u'VP  13': [u'VV \u71c3\u70e7 14',                                                                {u'NP  15': [u'NN \u80f6 16',                                                                             u'NN \u5236\u54c1 17']}]},                                                   {u'VP  18': [u'VV \u6392\u653e 19',                                                                {u'NP  20': u'NN \u5e9f\u6c14 21'}]}]}]}]},             u'PU \u3002 22']}] #ROOT为最外层ID=1,其他按字符的出现次序递增 #字符后面加个ID 是当字符相同时用ID 区别他们

 

  故,自己写了一个算法,先把算法逻辑po上。

#1.分层及父级计算算法    #1.1分层:        #条目所在层数=条目ID值-条目前”)”数目    #1.2条目的父级条目计算公式:        #if ∆”)”==0:父ID=self.ID-1        #if ∆”)”>0:父ID=查找self.ID之前的数据,选取最后层数=当前条目层数的父ID为自身的父ID(其中∆”)”为相邻的两个条目的右括号数目之差,如NN的父ID为8、VP的父ID为7)

附上代码:

 

# -*- coding:utf-8 -*-import refrom pprint import pprintfrom pandas import DataFrameclass Transtrees:        """        将字符串按“)”数目分层和计算父节点ID        1、层数的计算公式为ID-")"数目        2、父节点计算方式为:                ∆")"数目 =0:父ID 为自身ID-1                ∆")"数目 >0 :父ID 为搜索自身之前所有的ID,取最后层数相同的节点的父ID为自身父ID                例如:                u'(ROOT(IP(LCP(IP(NP(NN)) VP(VV)))))'                ROOT IP LCP IP NP NN VP VV        id      1    2  3   4  5  6  7  8        ")"     0    0  0   0  0  0  2  2        floor   1    2  3   4  5  6  5  6          fid     0    1  2   3  4  5  4  7         """    def __init__(self,strtree):                """                初始化的同时,加载数据结果                _nlist 为一个装有[id,文本,右括号数目,层数]的列表                _fid_dict 是一个格式如{id:父ID}的字典                _tree_data 是一个装有[id,文本,层数,父ID]的列表                """        self._strtree = strtree        self._nlist = []        self._nlist = self.get_ID_COUNT()        self._fid_dict ={}        self._fid_dict = self.get_fid()        self._tree_data =[]        self._tree_data = self.get_tree_data()    def get_ID_COUNT(self):        flag=1        namelist = re.findall("[^()]+",self._strtree)        while flag:            try:                namelist.remove(' ')            except:                flag=0        for i in range(len(namelist)):            name_index = len(self._strtree)-len(self._strtree.split('(',i+1)[-1])-1            bk_count = self._strtree[:name_index].count(')')            self._nlist.append([i,namelist[i],bk_count,i-bk_count])        return self._nlist    def get_fid(self):        treedata = DataFrame(self._nlist, columns=["ID", "TEXT", "BK_COUNT", "FLOOR"])        tag=0        for i in range(1,len(treedata)):            if treedata["BK_COUNT"][i] == treedata["BK_COUNT"][i-1]:                 self._fid_dict[i] = treedata['ID'][i-1]            else:                for j in range(1,i):                    if treedata['FLOOR'][j] == treedata['FLOOR'][i]:                        self._fid_dict[i] = self._fid_dict[j]        self._fid_dict[0] =-1        return self._fid_dict    def get_tree_data(self):        for i in range(len(self._nlist)):            self._tree_data.append([str(i+1),self._nlist[i][1]+' '+str(i+1),str(self._fid_dict[i]+1)])        return self._tree_dataclass bandModel:        """        绑定父子关系辅助类        """    def __init__(self, ID, TEXT, FID):        self._ID = ID        self._TEXT = TEXT        self._FID = FID        self._children = []    def addChild(self, *child):        self._children += child    def printTree(self,blist):                """                blist 返回的结果为:(以u'(ROOT(IP(LCP(IP(NP(NN)) VP(VV)))))'为例子)                [{VP:VV},{NP:NN},{IP:NP},{LCP:IP},{IP:LCP},{ROOT:IP}]                即由深到浅,每层的父子关系的列表。                """        map(lambda child:child.printTree(blist), self._children)        for i in self._children:            blist.append({self._TEXT:i._TEXT})def get_tree(a,b):        """        根据bandModel生成的blist重构树状结构        """    if b.values()[0] in a.keys():        if (b.keys()[0] in a.keys()) & (b.values()[0] in a.keys()):            if isinstance(a[b.keys()[0]], list):                a[b.keys()[0]].append({b.values()[0]:a.pop(b.values()[0])})                return a            a[b.keys()[0]] =[a[b.keys()[0]],{b.values()[0]:a.pop(b.values()[0])}]            return a        if b.keys()[0] in a.keys():            a[b.keys()[0]].append({b.values()[0]:a.pop(b.values()[0])})        a[b.keys()[0]] = {b.values()[0]:a.pop(b.values()[0])}        return a    for k in range(len(a.keys())):        if a.keys()[k] == b.keys()[0]:            if isinstance(a[b.keys()[0]], list):                a[b.keys()[0]].append(b.values()[0])                return a            a[b.keys()[0]] =[a[b.keys()[0]], b.values()[0]]            return a        return dict(a,**b)def get_id(tree,strs=None):    """        查找时的辅助函数,获取输入字符串的id列表        """    id_list = []    data = DataFrame(tree._nlist,columns=['id', 'text', 'bk_count', 'floor'])    for i in range(len(tree._nlist)):        if len(re.findall("^"+strs,data['text'][i])) == 1 :            id_list.append(i+1)    return id_listdef get_result(tree,strs):        """        结果返回        id_list 查找的字符串的id的列表        tree_list 每个ID节点的具体结构组成的列表        """    alist=[]    blist=[]    tree_list=[]    for i in tree._tree_data:        alist.append(bandModel(i[0],i[1],i[2]))    for i in range(0, len(alist)):        for j in range(0, len(alist)):            if alist[j]._FID == alist[i]._ID:                alist[i].addChild(alist[j])    id_list = get_id(tree, strs)    if len(id_list) == 0:        return "'%s' is not the nodes of the tree!" % strs,id_list    else:        z=0        for i in id_list:            if len(alist[i-1]._children) == 0:                tree_list.append("%s is the deepest nodes of the tree!" % tree._nlist[i-1][1])            else:                alist[i-1].printTree(blist)        z=reduce(get_tree,blist)        if z :            tree_list.append(z)        return tree_list,id_listif __name__ == '__main__':    tree=Transtrees(u"(ROOT (IP (ADVP (AD \u4f46)) (NP (NN \u52a0\u5de5\u5382)) (VP (ADVP (AD \u8fd8\u662f)) (VP (VV \u7ee7\u7eed) (VP (VP (VV \u71c3\u70e7) (NP (NN \u80f6) (NN \u5236\u54c1))) (VP (VV \u6392\u653e) (NP (NN \u5e9f\u6c14)))))) (PU \u3002)))")        tree_list,id_list=get_result(tree,'IP')        pprint(tree_list)

  完全手工,因为只是一个抽取工具,所以没有做相应的优化。

  个人劳动成果,转载请注明。

转载于:https://www.cnblogs.com/guapeng/p/4683426.html

你可能感兴趣的文章
JBOSSAS 5.x/6.x 反序列化命令执行漏洞(CVE-2017-12149)
查看>>
Zookeeper zkui-zookeeper图形化管理工具
查看>>
java运行时内存分类
查看>>
为什么说 Git 比 SVN 更好
查看>>
1.基础数据类型的初识 字符串 bool 整型 if else elif
查看>>
【设计模式】4、原型模式
查看>>
进入meta模式关闭背光灯
查看>>
轻松实现Ecshop商城多语言切换
查看>>
webstorm上svn的安装使用
查看>>
【JEECG技术文档】数据权限自定义SQL表达式用法说明
查看>>
使用 Bootstrap Typeahead 组件
查看>>
EF不能很好的支持DDD?估计是我们搞错了!
查看>>
ubuntu下基于sqlite3后台的php环境的搭建
查看>>
Qt 静态库与共享库(动态库)共享配置的一个小办法
查看>>
linux_cacti 配置之 安装snmp 服务
查看>>
201407-至今
查看>>
c# 应用事务
查看>>
优化杭州某著名电子商务网站高并发千万级大型数据库经验之- SQL语句优化(转)...
查看>>
DtCms.Model.Article.cs
查看>>
WPF——TargetNullValue(如何在绑定空值显示默认字符)
查看>>