Python技术迷

麻了!刚到新公司就让我请客,还指定2888元的海鲜套餐

刚入职第一天,工牌还没捂热,同事先把饭局给你安排明白了:欢迎新人可以,直接点名2888的海鲜套餐,这味儿就不对了。说白了,这哪是欢迎,像收“入场费”。

Image

我最烦这种默认你懂规矩。你是来上班的,不是来认山头的。请杯奶茶、带点零食,算个意思,大家哈哈一笑也就过去了。上来就2888,HR看完估计都得装没看见。一个团队要靠宰新人找气氛,那这气氛本身就挺穷的。

这种局真别硬撑。你今天咬牙请了,后面他们只会觉得你“懂事”,不会觉得你不容易。

算法题:删除注释

代码看着没几行,真写起来最容易翻车的地方,不在 #,也不在 //,而在 /* ... */ 跨行注释。

这种题我第一眼就不太信那些“遇到注释就删掉” 的写法。删注释不是替换字符串,尤其是块注释跨了两三行以后,上一行剩下半截,下一行又接上半截,处理顺序一乱,结果就歪了。

这题其实就盯住一件事:当前是不是正处在块注释里。

只要这个状态控住了,事情就简单很多。逐行扫,逐字符看:

  • 如果当前不在块注释里,先判断是不是遇到 /*,遇到了就进块注释状态。
  • 如果当前不在块注释里,遇到 //,这一行后面直接不要了。
  • 如果当前在块注释里,就一直找 */,找到才退出。
  • 只有不在块注释里的普通字符,才真正写进结果。

这种题不需要整花活,一个布尔变量比一堆切片可靠。

代码我自己一般会这么写,短一点,现场感也强:

from typing import List

classSolution:
defremoveComments(self, source: List[str]) -> List[str]:
        ans = []
        in_block = False
        line_buf = []

for line in source:
            i = 0
ifnot in_block:
                line_buf = []

while i < len(line):
ifnot in_block:
if i + 1 < len(line) and line[i] == '/'and line[i + 1] == '*':
                        in_block = True
                        i += 2
elif i + 1 < len(line) and line[i] == '/'and line[i + 1] == '/':
break
else:
                        line_buf.append(line[i])
                        i += 1
else:
if i + 1 < len(line) and line[i] == '*'and line[i + 1] == '/':
                        in_block = False
                        i += 2
else:
                        i += 1

ifnot in_block and line_buf:
                ans.append(''.join(line_buf))

return ans

这里有两个细节,漏一个基本就错。

第一个,line_buf 不能每次都清空。只有不在块注释里开始新行的时候才重置。因为块注释可能把一段代码切成两半:

["ab/*x", "y*/cd"]

最后应该拼成 "abcd",不是两行,也不是空。

第二个,结果里不要把空串塞进去。删完注释后这一行如果没内容,直接跳过。不然后面输出会多出一堆空行。

再拿一个例子过一下:

source = [
"int a = 1; /* test",
"xxx */ int b = 2;",
"int c = 3; // ok"
]

扫完以后得到:

[
"int a = 1;  int b = 2;",
"int c = 3; "
]

这题本质上就是个小型状态机。别上来就 replace,也别想着正则一把梭。注释一跨行,正则和替换都容易把自己绕进去。老老实实维护 in_block,一位一位扫,反而最稳。