【Python力扣722】过滤掉注释

题目来源:https://leetcode.cn/problems/remove-comments/

题目研读

给一个 C++ 程序,删除程序中的注释。这个程序source是一个数组,其中source[i]表示第 i 行源码。 这表示每行源码由
‘\n’ 分隔。

在 C++ 中有两种注释风格,行内注释和块注释。

字符串// 表示行注释,表示//和其右侧的其余字符应该被忽略。 字符串/*
表示一个块注释,它表示直到下一个(非重叠)出现的*/之间的所有字符都应该被忽略。(阅读顺序为从左到右)非重叠是指,字符串/*/并没有结束块注释,因为注释的结尾与开头相重叠。
第一个有效注释优先于其他注释。

如果字符串//出现在块注释中会被忽略。 同样,如果字符串/*出现在行或块注释中也会被忽略。
如果一行在删除注释之后变为空字符串,那么不要输出该行。即,答案列表中的每个字符串都是非空的。

样例中没有控制字符,单引号或双引号字符。

比如,source = “string s = “/* Not a comment. */”;” 不会出现在测试样例里。
此外,没有其他内容(如定义或宏)会干扰注释。

我们保证每一个块注释最终都会被闭合, 所以在行或块注释之外的/*总是开始新的注释。

最后,隐式换行符可以通过块注释删除。 有关详细信息,请参阅下面的示例。

从源代码中删除注释后,需要以相同的格式返回源代码

示例

输入: source = [“/*Test program /", “int main()”, "{ ", " // variable declaration ", “int a, b, c;”, "/ This is a test”, " multiline “, " comment for “, " testing */”, “a = b + c;”, “}”]
输出: [“int main()”,”{ “,” “,“int a, b, c;”,“a = b + c;”,”}"]
解释: 示例代码可以编排成这样:
/*Test program /
int main()
{
// variable declaration
int a, b, c;
/* This is a test
multiline
comment for
testing */
a = b + c;
}
第 1 行和第 6-9 行的字符串 /
表示块注释。第 4 行的字符串 // 表示行注释。
编排后:
int main()
{
int a, b, c;
a = b + c;
}

思路

  1. 通过正则表达式进行匹配,找到需要替换的行。
  2. 将注释行替换成空行。
  3. 最后过滤空行。

具体实施

  1. 利用python中的join函数,先将整个列表中的元素归为一个长的大字符串。
str='\n'.join(source)

这样的话,形成的字符串str将是待检测的长字符串

/*Test program */
int main()
{ 
 // variable declaration 
int a, b, c;
/*This is a test
multiline
 comment for 
 testing */
a = b + c;
}
  1. 构建正则表达式
    首先匹配分为两种,一种是//及其之后的任意字符;另外一种是匹配/*和*/之间的字符,其中/*和*/可能在同一行也可能不在同一行,所以对于其匹配我们要采用非贪婪模式,避免删掉正常的代码部分。
匹配条件1//.*  表示匹配到//及其之后任意一个字符
匹配条件2/\*(.|\n)*?\*/   前后两个表示匹配到/**/注意要用到转义字符。
匹配之后在/**/之间要么匹配任意字符,要么匹配换行符,所以是(.|\n)*
之后加上非贪婪模式?
  1. 利用re.sub函数替换字符串
re库中的sub函数最基础需要传入3个变量 正则表达式, 替换成目的字符串,待替换字符串
re.sub('//.*|/\*(.|\n)*?\*/', '', '\n'.join(source)
替换之后的效果为:
 
int main()
{ 
  
int a, b, c;
 
a = b + c;
}

  1. 将大字符串还原成列表
    利用列表分片方法将大字符串拆成列表:
re.sub('//.*|/\*(.|\n)*?\*/', '', '\n'.join(source).split('\n')
这样得到的效果如下:
['', 'int main()', '{ ', ' ', 'int a, b, c;', '', 'a = b + c;', '}']

利用python中的filter函数处理掉多余的空行,之后用list还原成列表

filter(None, re.sub('//.*|/\*(.|\n)*?\*/', '', '\n'.join(source).split('\n')))
list(filter(...))
最终效果如下:
['int main()', '{ ', ' ', 'int a, b, c;', 'a = b + c;', '}']

全部的代码

class Solution:
    def removeComments(self, source: List[str]) -> List[str]:
        # 匹配所有 // 和 /* */,后者用非贪婪模式。将所有匹配结果替换成空串。最后移除多余空行。
        return list(filter(None, re.sub('//.*|/\*(.|\n)*?\*/', '', '\n'.join(source)).split('\n')))

正则表达式知识:

. 可以匹配除换行符之外的任何字符,如果有re.DOTALL标志,则匹配任意字符包括换行
\d 匹配一个Unicode数字,如果带re.ASCII,则匹配0-9
\D 匹配Unicode非数字
\s 匹配Unicode空白,如果带有re.ASCII,则匹配\t\n\r\f\v中的一个
\S 匹配Unicode非空白
\w 匹配Unicode单词字符,如果带有re.ascii,则匹配[a-zA-Z0-9_]中的一个
\W 匹配Unicode非单子字符
量词
? 匹配前面的字符0次或1* 匹配前面的字符0次或多次
+ 匹配前面的字符1次或者多次
{m} 匹配前面表达式m次
{m,} 匹配前面表达式至少m次
{,n} 匹配前面的正则表达式最多n次
{m,n} 匹配前面的正则表达式至少m次,最多n次
以上量词默认贪婪模式,会尽可能多的匹配,如果要改为非贪婪模式,通过在量词后面跟随一个?来实现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值