面试题:转置文件,别一上来就 split 全量读
这题看着像字符串处理,真到命令行环境里,考的其实是你对“行列转换”这件事有没有想清楚。
先说题意。文件内容大概这样:
name age citytom 18 bjjack 20 sh
要求转成:
name tom jackage 18 20city bj sh
也就是把原来按行存的数据,按列重新输出。
很多人上来就这么写:
with open("input.txt", "r", encoding="utf-8") as f: rows = [line.strip().split() for line in f]for col in zip(*rows): print(" ".join(col))
这段代码能过大多数样例,而且很直观。rows 先把每一行拆成数组,zip(*rows) 再把行转成列。
但这题真正容易翻车的地方,不在转置本身,在输入细节。
比如文件里可能有多余空格:
name age citytom 18 bjjack 20 sh
这时候直接 split() 反而是对的,因为它会自动吞掉连续空白。要是你写成 split(" "),中间就会夹出很多空字符串,结果列数都乱了。
再比如有些人喜欢手搓双层循环:
matrix = []with open("input.txt", "r", encoding="utf-8") as f:for line in f: matrix.append(line.strip().split())row_count = len(matrix)col_count = len(matrix[0])for c in range(col_count): part = []for r in range(row_count): part.append(matrix[r][c]) print(" ".join(part))
这个也没问题,而且在面试里有个好处:你能顺手解释“为什么是先列后行”。面试官一般不怕你写慢一点,怕的是你自己都没搞明白下标到底谁是行谁是列。
不过还要补一句,这题默认每一行字段数一致。要是不一致,zip(*rows) 会按最短的那一行截断,后面的值直接没了。稳一点可以先做校验:
with open("input.txt", "r", encoding="utf-8") as f: rows = [line.strip().split() for line in f if line.strip()]width = len(rows[0])for i, row in enumerate(rows):if len(row) != width:raise ValueError(f"第{i+1}行列数不一致: {row}")for col in zip(*rows): print(" ".join(col))
这就像线上处理文本文件时常做的第一步,不急着算,先看数据齐不齐。
如果让我在面试里交答案,我会写这个版本,够短,也够稳:
deftranspose_file(path: str) -> None:with open(path, "r", encoding="utf-8") as f: rows = [line.strip().split() for line in f if line.strip()]ifnot rows:return size = len(rows[0])for row in rows:if len(row) != size:raise ValueError("输入文件不是规整矩阵")for col in zip(*rows): print(" ".join(col))transpose_file("input.txt")
这题不难,但挺适合拿来看基本功。代码能不能一次写对,往往就看两个点:有没有把输入当回事,和有没有把“转置”真的当成行列互换,而不是机械背模板。