通过使用Pythonsorting文本文件
我有一个包含超过10万行的文本文件。 这样的行:
37024469;196672001;255.0000000000 37024469;196665001;396.0000000000 37024469;196664001;396.0000000000 37024469;196399002;85.0000000000 37024469;160507001;264.0000000000 37024469;160506001;264.0000000000
正如你所看到的,分隔符是“;”。 我想通过使用python根据第二个元素来sorting这个文本文件。 我不能使用拆分function。 因为它导致MemoryError。 我如何pipe理它?
内存中不要sorting1000万行。 分批分解:
-
运行100 100k行sorting(使用该文件作为迭代器,结合使用
islice()
或类似的select批处理)。 写出来在其他地方分开文件。 -
合并sorting的文件。 这里是一个合并生成器,你可以传递100个打开的文件,它会按照sorting顺序产生行。 逐行写入新文件:
import operator def mergeiter(*iterables, **kwargs): """Given a set of sorted iterables, yield the next value in merged order Takes an optional `key` callable to compare values by. """ iterables = [iter(it) for it in iterables] iterables = {i: [next(it), i, it] for i, it in enumerate(iterables)} if 'key' not in kwargs: key = operator.itemgetter(0) else: key = lambda item, key=kwargs['key']: key(item[0]) while True: value, i, it = min(iterables.values(), key=key) yield value try: iterables[i][0] = next(it) except StopIteration: del iterables[i] if not iterables: raise
基于使用Python对2MB内存中的一百万个32位整数进行sorting :
import sys from functools import partial from heapq import merge from tempfile import TemporaryFile # define sorting criteria def second_column(line, default=float("inf")): try: return int(line.split(";", 2)[1]) # use int() for numeric sort except (IndexError, ValueError): return default # a key for non-integer or non-existent 2nd column # sort lines in small batches, write intermediate results to temporary files sorted_files = [] nbytes = 1 << 20 # load around nbytes bytes at a time for lines in iter(partial(sys.stdin.readlines, nbytes), []): lines.sort(key=second_column) # sort current batch f = TemporaryFile("w+") f.writelines(lines) f.seek(0) # rewind sorted_files.append(f) # merge & write the result sys.stdout.writelines(merge(*sorted_files, key=second_column)) # clean up for f in sorted_files: f.close() # temporary file is deleted when it closes
自Python 3.5以来, heapq.merge()
具有key
参数 。 你可以尝试从Martijn Pieters的答案中得到mergeiter()
,或者在旧的Python版本上进行Schwartzian变换 :
iters = [((second_column(line), line) for line in file) for file in sorted_files] # note: this makes the sort unstable sorted_lines = (line for _, line in merge(*iters)) sys.stdout.writelines(sorted_lines)
用法:
$ python sort-k2-n.py < input.txt > output.txt
你可以用os.system()
调用bash函数sort
sort -k2 yourFile.txt