代码抽取功能优化(二)

本文详述了代码抽取功能的优化过程,包括提取markdown中的code、python和C++多行注释,提升了准确率至92%。介绍了代码判定逻辑,并讨论了后续优化方向,如增加对SQL和汇编代码的支持,以及平衡效率与准确率的问题。
摘要由CSDN通过智能技术生成


前言

本文基于上篇代码抽取功能优化(一)进行了一些优化,增加了对python多行注释、C++多行注释以及markdown的处理,修复了一些小bug,将抽取准确率提升至92%。


一、代码抽取构建思路

在这里插入图片描述

二、各模块介绍

1.提取markdown中的code

思路:
1、判断```是否在该行中,在的话count+1,并取出该行行号
2、得到行号后,从原list中取出行号之间的内容
整体还需看代码才能更好的理解

def extract_markdown(data_list):
    """提取markdown中的代码,即"```"中的内容
    Args:
        data_list: 文本列表
    Returns:
        codes: 提取出来的代码段(list)
        texts: 提取出的文本(string类型)
    """
    idxs = []
    count = 0
    for idx, line in enumerate(data_list):
        if "```" in line:
            idxs.append(idx)
            count += 1
    if count < 2:
        return [], data_list
    else:
        try:
            assert (len(idxs) % 2) == 0
            codes = []
            texts = []
            for idx, val in enumerate(idxs):
                if idx % 2 == 0:
                    if idx == 0:
                        text = data_list[:idxs[idx]]
                    else:
                        text = data_list[idxs[idx - 1] + 1: idxs[idx]]

                    code = data_list[idxs[idx] + 1: idxs[idx + 1]]
                    code = '\n'.join(code)
                    text = '\n'.join(text)
                    codes.append(code)
                    texts.append(text)
                if idx == len(idxs) - 1:
                    text = data_list[idxs[idx] + 1:]
                    text = '\n'.join(text)
                    texts.append(text)
            texts = ''.join(texts)
        except:
            return [], data_list
        return codes, texts

2.提取python多行注释的索引

整体思路与提取markdown中的code类似,这里不再赘述,直接看代码:

def extract_py_annotation_idx(data_list, annotation= "'''"):
    """提取python多行注释内容
    Args:
        data_list: 文本列表
    Returns:
        idx: 返回的索引
    """
    idxs = []
    count = 0
    for idx, line in enumerate(data_list):
        if annotation in line:
            idxs.append(idx)
            count += 1
    if (count % 2) == 1:
        return []
    else:
        assert (len(idxs) % 2) == 0
        return idxs

3.提取C++多行注释

这里与前面两个稍有不同,但整体思路也是一样

def extract_cpp_annotation_idx(data_list):
    """提取/* */中的多行注释行索引
    Args:
        data_list: 文本列表
    Returns:
        idx: 注释索引列表
    """
    idxs = []
    count = 0
    for idx, line in enumerate(data_list):
        if line.find('/*') != -1 and line.find('*/') != -1:
            continue
        elif line.find('/*') != -1:
            count += 1
            idxs.append(idx)
        elif line.find('*/') != -1:
            count += 1
            idxs.append(idx)
    if (count % 2) == 1:
        return []
    else:
        return idxs

不管是哪种代码的多行注释,都需要注意一点:这些注释符一定是成对存在的!

4.代码判定逻辑

1、输入为line,对每一行代码进行判定,是代码返回True,否则返回False。
2、对传入的line,先直接判定为False,满足一定的条件后,再置为True。


def is_code_new(self, line, feature_list, annotation_list, text_keywords_list, code_print_list):
    code_flag = False #先置为False,满足一定条件后再判定为True
    # count = 0
    # cn_num = getnum_of_cn(line)
    # en_num = getnum_of_en(line)
    cn_and_symbol_num = getnum_of_cn_and_symbol(line) # 计算中文字符及中文标点符号的个数
    for symbol in feature_list:  # 遍历代码关键字
        if is_sub_string(line, symbol):   # 判断该行是否包含代码关键字
            code_flag = True	#包含的话,置为True
            for annotation in annotation_list:	#遍历各种代码的注释符
                if is_sub_string(line, annotation):	#判定是否包含注释符
                    code_flag = True	#包含注释符,置为True,跳出注释遍历
                    break
                else:		#不包含注释符
                    for text_keyword in text_keywords_list:	#遍历文本关键词,如果包含文本关键词,置为False
                        if is_sub_string(line, text_keyword):
                            code_flag = False
                            break
                    if cn_and_symbol_num > 30:
                    	# 如果不包含注释,且中文字符数大于30,则置为False
                    	# 考虑到大于30个中文字符,也有可能是print的情况,因此该段代码必须放在判断print条件之前
                        code_flag = False
					# 如果不包含注释,且中文字符数大于0,便考虑是否是print输出的情况
					# 如果确实是print的输出,则置为True
                    if cn_and_symbol_num > 0:
                        for print_keyword in code_print_list:
                            if is_sub_string(line, print_keyword):
                                code_flag = True
                                break
                            else:
                            #如果不是print的情况,则考虑到是否是定义的字典
                            # 如python定义字典,里面存在这种情况:
                            # dict = {
                            #		  'name' : '张三',
                            # 		  '性别': '男'
                            #		 }
                            #如果是上述类似情况,则置为True
                                if re.search(r'[\=\:]\s*?[\'\"].*?[\'\"]', line):
                                    code_flag = True
                                else:
                                    code_flag = False
                   
    # 考虑到有些报错也会被误判为代码,这里排除类似以下情况的报错
    # Trace back in line xxx
    # 其中xxx可以是任意数字
    # 只要该行包含line xxx,则置为False
    if is_line_num(line):
        code_flag = False
    return code_flag

5.后续的优化

1、虽然准确率已经有90+%,但测试数据仅有400条,可能漏掉了一些情况,比如SQL代码,51汇编代码,以及一些其他的关键字段,后续会围绕这几个点去优化,争取将效果提升至95+%。
2、考虑过将所有语言的保留字加入code_feature_list中,但这样的话,准确率虽然有所提升,但代码执行效率将下降很多,由于代码提取服务作为一个基础模块,必须要兼顾效率及准确率,因此,两者需有个平衡。

总结

1、经过20多天的努力,终于将代码提取服务的效果提升至90+%,也算是个不错的开始。
2、一个人或许可以走得很快,但一群人却能够走的更远
3、感恩遇见这么好的一个团队🌹🌹🌹
4、加油

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ToTensor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值