像这样的东西应该做你想做的事。
import itertools as it
with open('test.txt') as in_file:
splitted_lines = (line.split(None, 1) for line in in_file)
for num, group in it.groupby(splitted_lines, key=lambda x: x[0]):
with open(num + '.txt', 'w') as out_file:
out_file.writelines(line for _, line in group)
- 该
with
声明允许安全地使用资源。在这种情况下,它们会自动关闭文件。
- 该
splitted_lines = (...)
行在接受每一行的字段上创建一个可迭代对象,并产生一对第一个元素,其余行。
itertools.groupby
函数是完成大部分工作的函数。它遍历文件的行并根据第一个元素对它们进行分组。
(line for _, line in group)
迭代“分割线” 。它只是删除第一个元素并仅写入其余行。(与_
其他任何标识符一样,这只是一个标识符。我可以使用x
or first
,但我_
经常用来表示您必须分配但您不使用的东西)
我们可能可以简化代码。例如,最外层with
不太可能有用,因为我们只是在阅读模式下打开文件,而不是修改它。删除它我们可以取消缩进:
import itertools as it
splitted_lines = (line.split(None, 1) for line in open('test.txt'))
for num, group in it.groupby(splitted_lines, key=lambda x: x[0]):
with open(num + '.txt', 'w') as out_file:
out_file.writelines(line for _, line in group)
我做了一个非常简单的基准测试来测试 python 解决方案与 awk 解决方案。性能大致相同,python使用每行有 10 个字段的文件稍快一些,并且有 100 个“行组”,每个随机大小在 2 到 30 个元素之间。
python代码的时序:
In [22]: from random import randint
...:
...: with open('test.txt', 'w') as f:
...: for count in range(1, 101):
...: num_nums = randint(2, 30)
...: for time in range(num_nums):
...: numbers = (str(randint(-1000, 1000)) for _ in range(10))
...: f.write('{}\t{}\n'.format(count, '\t'.join(numbers)))
...:
In [23]: %%timeit
...: splitted_lines = (line.split(None, 1) for line in open('test.txt'))
...: for num, group in it.groupby(splitted_lines, key=lambda x: x[0]):
...: with open(num + '.txt', 'w') as out_file:
...: out_file.writelines(line for _, line in group)
...:
10 loops, best of 3: 11.3 ms per loop
awk 时间:
$time awk '{print $2,$3,$4 > ("test"$1)}' OFS='\t' test.txt
real 0m0.014s
user 0m0.004s
sys 0m0.008s
请注意,0.014s
大约是14 ms
.
无论如何,根据操作系统负载,时间可能会有所不同,并且实际上它们同样快。实际上,几乎所有时间都在读取/写入文件,这可以通过 python 和 awk 有效地完成。我相信使用 C 你不会看到巨大的速度提升。