目前在做文本主题提取和分词,遇到一个很有意思的低级问题,同时可以体现一种很普遍的解题思路,现记录下来。
如下,有个list,对,就是这货。

bad_sents = ['此条工单内容显示:该市民反应的问题是']

sents = ['此条工单内容显示:该市民反应的问题是', 
        '此条工单内容显示:该市民反应的问题是', 
        '1、问题描述:平潮镇九圩港村停水事宜', 
        '部门处理']

目标需求

  • ①筛选掉 ‘此条工单内容显示:该市民反应的问题是’
  • ②筛选掉长度小于等于5的记录。

最终大神的指点下的实现代码:

sents = [x for x in sents if x not in bad_sents and len(x) > 5] #列表生成式,膜拜啊

注:如果你没有兴趣读下去,可以到此为止了,后面的是关于我智障解题思路的记录。


解题思路:
刚开始的核心思路是“剔除”不满足条件的记录。于是写下了个新手很容易犯错误的代码,如下:

bad_sents = ['此条工单内容显示:该市民反应的问题是']

    for i, sent in enumerate(sents):
        print(i,sent)
        if sent in bad_sents or len(sent) <= 5:
            # 剔除不符合的对象
            print(sents.pop(i))
        else:
            pass

然后查看结果,sents,懵逼了,怎么还有一条记录:’此条工单内容显示:该市民反应的问题是’。
我想,可能是因为有重复对象的原因,pop只会pop出第一个元素(这种想法是错误的),尝试用remove。
代码修改如下:

for sent in sents:
        print(sent)
        print('####################')
        if sent in bad_sents or len(sent) <= 5:
            # 剔除不符合的对象
            print(sents.remove(sent))
        else:
            pass

兴冲冲的运行,哎呦,怎么和上面的结果一样。。。。。。

百思不得其解,大神看了一眼,傻啊,怎么能在循环中操作列表呢。你每把一个元素删除出去,列表都会更新成新的列表。也就是说:我在用原列表的index和item(sent)去匹配操作不断变化的新列表!(突然想到了闭包的相关知识:返回函数不要引用任何循环变量,或者后续会发生变化的变量。)

那怎么做呢,需要一个深度copy对象,把原列表保存在sentstmp中。

import copy
        sentstmp = copy.deepcopy(sents)  

        for i, sent in enumerate(sentstmp):
            print(sent)
            if sent in bad_sents or len(sent) <= 5:
                try:
                    sents.pop(i)
                except:
                    pass
            else:
                pass

大神啪啪啪就敲出了这段代码,正在我赞叹之余,大神笑了笑,你的思路就不“正常”,为什么不思考“挑出符合条件”的数据呢?来,我给你写一行让你无地自容的代码。

sents = [x for x in sents if x not in bad_sents and len(x) > 5]

我的天,强无敌啊!


————–分割线—————-
后来,我不断的把bad_sents丰富,并觉得可以用正则表达式实现,如下是部分代码:

bad_sents = [r'此条工单内容显示:该市民反应的问题.*'
                , r'.*问题描述:市民来电'
                , r'.*问题描述:电话接通后'
                , r'已按服务规范应答'
                , r'市民来电反映:.*下午'
                , r'来电时间:\d{4}/\d{1,2}/\d{1,2}\s*\d{1,2}:\d{2}:\d{2}'
                , r'..诉求目的.'
                ]

    # 去掉无意义的句子,这段niubility的代码被我小小的更改了下
    for bad_sent in bad_sents:

        sents = [x for x in sents if re.match(bad_sent, x) is None and len(x) > 2]