heapq.merge()
如果标准库中有,为什么要自己滚动?不幸的是,它没有提供一个关键的论点——你必须自己做装饰 - 合并 - 不装饰的舞蹈:
from itertools import imap
from operator import itemgetter
import heapq
def extract_timestamp(line):
"""Extract timestamp and convert to a form that gives the
expected result in a comparison
"""
return line.split()[1] # for example
with open("log1.txt") as f1, open("log2.txt") as f2:
sources = [f1, f2]
with open("merged.txt", "w") as dest:
decorated = [
((extract_timestamp(line), line) for line in f)
for f in sources]
merged = heapq.merge(*decorated)
undecorated = imap(itemgetter(-1), merged)
dest.writelines(undecorated)
上面的每一步都是“偷懒”的。因为我避免file.readlines()
根据需要读取文件中的行。同样,使用生成器表达式而不是列表组合的装饰过程。heapq.merge()
也是懒惰的——每个输入迭代器需要一个项目同时进行必要的比较。最后,我使用itertools.imap()
了内置的 map() 的惰性变体来取消装饰。
(在 Python 3 中 map() 变得懒惰了,所以你可以使用它)