朋友说他们组有个30岁、年薪85万的高级工程师,被调离了核心项目。原因不是技术不行,而是拒绝参与流程管理和协作优化。
刷到个吐槽:朋友公司里有位30岁高级工程师,年薪85万,技术很能打,却被从核心项目挪走。不是写不动代码,而是他死活不肯碰流程、协作这些“非技术活”。管理会上领导一句话挺扎心:能冲刺,但不愿意带队拉磨。
我能理解他的心态:很多人学技术就是想把活干漂亮,不想被会议、表格、对齐进度消耗掉。但现实是,核心项目拼的不只是个人输出,更是团队效率和可复制性。你可以不当管理者,可一旦在关键岗位,至少要愿意把自己的经验变成大家都能用的办法。
说白了,高薪不是只买代码能力,也买你对整体交付负责的态度。技术人想走得更远,别只做“快马”,也得学会在关键时候“拉车”。
算法题:简化路径
那天我在机房门口等电梯,手里端着咖啡,群里突然有人@我:哥,线上有个“文件预览”接口又抽风了,明明传的是 ///a//b/../c/./,落盘日志里却变成了奇奇怪怪的目录……我当时第一反应不是查业务,而是想起以前抓包抓到想吐那种事儿——协议里多读一个字节,后面全错位,越看越像“路径解析”这种小问题把人坑死。
然后我就跟他说,别急,先把“路径”当成一段要被解析的输入流,别把它当字符串拼接。路径这玩意儿最烦的就是:/ 可能连续、. 表示原地踏步、.. 表示回退一层,还要保证最后输出一定是规范的“绝对路径”。你要是边 split 边拼,十有八九就会出现 //、空段、或者回退越界这种脏结果,最后线上报警还不好定位,跟 SpringBoot 那些“默认没配就坑你”的感觉一模一样。
我一般就用一个栈,真就土办法但稳:
先按 /切开,切完会有很多空串(连续斜杠造成的),直接跳过遇到 .跳过遇到 ..就 pop(如果栈为空也别慌,说明在根目录再退也还是根)其他正常目录名 push 最后把栈用 /拼回去,前面再补一个根的/。你看,逻辑就跟“请求链路追踪”一样,步骤别乱,别想当然。
代码我直接给你们贴一份,够干净也够抗揍,写完我还顺手打了几个用例,省得你们又说“我本地是好的上线就不行”这种话,哈哈。
from __future__ import annotations
defsimplify_path(path: str) -> str:
"""
简化 Unix 风格的绝对路径:
- 多个 / 视为一个
- . 忽略
- .. 回到上一级(根目录再 .. 仍是根)
"""
stack: list[str] = []
# split 会产生空段,比如 "///a//b" -> ["", "", "", "a", "", "b"]
for part in path.split("/"):
if part == ""or part == ".": # 空段和原地踏步都无视
continue
if part == "..":
if stack: # 有得退就退一层
stack.pop()
# 栈空就说明在根目录,继续忽略
else:
stack.append(part)
return"/" + "/".join(stack)
if __name__ == "__main__":
tests = [
"/home/",
"/../",
"/home//foo/",
"/a/./b/../../c/",
"///a//b/../c/./",
"/a/../../b/../c//.//",
"/a//b////c/d//././/..",
]
for t in tests:
print(f"{t!r} -> {simplify_path(t)!r}")
你们看这个实现,核心就是“只认语义,不认表象”,输入再脏都无所谓,最后输出一定稳定。真正容易写错的点反而是一些小细节:比如 split("/") 以后空段要跳过;再比如遇到 .. 的时候别 pop 出异常(很多人图省事直接 stack.pop(),结果 /../ 这种一跑就炸)。
行了我咖啡也凉了,电梯还没来……你要是把这个题当面试题刷,那就到这;但你要是真上生产用,记得再加两条:入参不是绝对路径怎么办、以及目录名里如果出现奇怪字符你要不要校验,别到时候又半夜把人吵醒。