我想基于给定的ID从大文件(列表,10M+
行)中过滤记录。
selected_id = list() # 70k+ elements
for line in in_fp: # input file: 10M+ lines
id = line.split()[0] # id (str type), such as '10000872820081804'
if id in selected_id:
out_fp.write(line)
以上代码非常耗时。我想到了一个想法。将selected_id
存储为dict
而不是list
。
有更好的解决方案吗?
答案 0 :(得分:1)
首先,为了从你的行中获取第一列,你可以使用csv
模块读取你的文件,使用正确的分隔符,使用zip()
函数(在python 3和pyhton 2 {{ 1}})和itertools.izip()
函数,以获取第一列,然后将结果传递给next()
函数,以保留唯一值。
set()
如果您想保留订单,可以使用import csv
with open('file_name') as f:
spam_reader = csv.reader(f, delimiter=' ')
unique_ids = set(next(zip(*spam_reader)))
:
collections.OrderedDict()
答案 1 :(得分:1)
你有一些问题,但只有第一个问题真的很讨厌:
list
的成员身份是O(n)
;对于70K元素list
,这是很多工作。设为set
/ frozenset
,查询通常为O(1)
,可节省数千次比较。如果类型不可删除,您可以预先sort
selected_list
并使用bisect
模块在O(log n)
时间内进行查找,这仍然会达到多个数量级如此大的list
加速。maxsplit
仅拆分足以获取ID selected_id
存储int
而不是str
并在读取时进行转换以便查找比较运行得快一点(这需要测试)。这可能不会产生重大影响,所以我将从示例中省略它。结合所有建议:
selected_id = frozenset(... Your original list of 70k+ str elements ...)
for line in in_fp: # input file: 10M+ lines
id, _ = line.split(None, 1) # id (str type), such as '10000872820081804'
if id in selected_id:
out_fp.write(line)
您甚至可以使用生成器表达式将for
循环转换为单个调用(尽管它有点过于紧凑),这会将更多工作推送到CPython中的C层,从而减少Python字节代码执行开销: / p>
out_fp.writelines(x for x in in_fp if x.split(None, 1)[0] in selected_id)