美文网首页
「Python」记一次凭想象重复造轮子的错误示范

「Python」记一次凭想象重复造轮子的错误示范

作者: HughDong | 来源:发表于2018-05-10 16:58 被阅读0次
    1. 读文档的意义在于知道别人已经实现了什么,怎么用
    2. 读源码的意义在于知道轮子是怎么造出来的
    3. 要好好学英语

    用了三天的时间造了一个方形轮子,记录下来以吸取教训。
    需求是用正则匹配一段文章,有n个匹配项,指定删除其中的某一个(第1个/第2个/倒数第1个...)
    Python re库的文档是英文的,在提不起兴趣一句一句翻译下,从这里开始走上了一条岔路。
    错误的实现思路:


    import re
    str1 = 'a1b1c1d1e.a2b2c2d2e.a3b3c3d3e.a4b4c4d4e.a5b5c5d5e.'
    rules = {
        'a\d{1}': 2,
        'b\d{1}': -1,
        'c\d{1}': -3,
        'd\d{1}': -3,
    }
    for (reg, index) in rules.items():
        if index < 0:  # 反向匹配
            front = str1
            rear = ''
            for i in range(abs(index)):
                try:
                    _front_ = re \
                        .search(r'.*(?=' + reg + ')', front) \
                        .group()
                    _cur_ = re \
                        .search(r'' + reg + '$', re.search(r'.*(' + reg + ')', front).group()) \
                        .group()
                    _rear_ = re.compile(r'.*(' + reg + ')').sub('', front)
                except AttributeError:
                    break
                else:
                    if i != (-1 - index):
                        rear = _cur_ + _rear_ + rear
                    else:
                        rear = _rear_ + rear
                    front = _front_
        else:  # 正向匹配
            front = ''
            rear = str1
            for i in range(index + 1):
                try:
                    obj = re.search(r'' + reg, rear)
                    start = obj.start()
                    end = obj.end()
                    _front_ = rear[0:start]
                    _rear_ = rear[end:]
                    _cur_ = rear[start:end]
                except AttributeError:
                    break
                else:
                    if i != index:
                        front = front + _front_ + _cur_
                    else:
                        front = front + _front_
                    rear = _rear_
        str1 = front + rear
    print(str1)
    

    正确的实现思路:
    re.finditer()返回的对象中包含了匹配项的开始/结束位置,只要把前后内容拼起来,丢弃匹配的位置就可以了。

    import re
    str1 = 'a1b1c1d1e.a2b2c2d2e.a3b3c3d3e.a4b4c4d4e.a5b5c5d5e.'
    rules = {
        'a\d{1}': 2,
        'b\d{1}': -1,
        'c\d{1}': -3,
        'd\d{1}': -3,
    }
    for (reg, index) in rules.items():
        pos = [(m.start(0), m.end(0)) for m in re.finditer(reg, str1)][index]
        print(pos)
        front = str1[:pos[0]]
        rear = str1[pos[1]:]
        str1 = front + rear
    print(str1)
    

    轮子跑起来后运行情况很糟糕,65000条数据清洗4条正则匹配项花了10分钟,更换完轮子方法后只用了2分钟。

    相关文章

      网友评论

          本文标题:「Python」记一次凭想象重复造轮子的错误示范

          本文链接:https://www.haomeiwen.com/subject/sdhtdftx.html