我有一个~1GB的数据条目文本文件和另一个名称列表,我想用它来过滤它们。浏览每个条目的每个名称将非常慢。在 python 中执行此操作的最有效方法是什么?如果名称嵌入在条目中,是否可以使用哈希表? 我可以使用名称部分始终放置的事实吗?
示例文件:
条目文件 -- 条目的每个部分都用制表符分隔,直到名称
246 lalala name="Jack";surname="Smith"
1357 dedada name="Mary";surname="White"
123456 lala name="Dan";surname="Brown"
555555 lalala name="Jack";surname="Joe"
名称文件 -- 每个文件都在换行符上
Jack
Dan
Ryan
所需输出 -- 仅名称文件中具有名称的条目
246 lalala name="Jack";surname="Smith"
123456 lala name="Dan";surname="Brown"
555555 lalala name="Jack";surname="Joe"
set
数据结构来存储名称 - 它提供了有效的查找,但如果名称列表非常大,那么您可能会遇到内存问题。
一般的想法是遍历所有名称,将它们添加到set
,然后检查数据文件中每行的每个名称是否包含在set
中。由于条目的格式没有变化,因此您应该能够使用简单的正则表达式提取名称。
如果在名称大小方面遇到问题 set
,则可以从 names 文件中读取 n 行,并对每组名称重复此过程,除非您需要排序。
我的第一直觉是制作一个以名称作为键的字典,假设使用字典中的键哈希查找名称是最有效的。
给定答案,通过@rfw,使用set
名称,我编辑了下面的代码,并使用dict
名称和set
针对两种方法对其进行了测试。
我建立了一个包含 40 多 M 条记录和 5400 多个名字的虚拟数据集。使用此数据集,set 方法在我的机器上始终具有优势。
import re
from collections import Counter
import time
# names file downloaded from http://www.tucows.com/preview/520007
# the set contains over 5400 names
f = open('./names.txt', 'r')
names = [ name.rstrip() for name in f.read().split(',') ]
name_set = set(names) # set of unique names
names_dict = Counter(names) # Counter ~= dict of names with counts
# Expect: 246 lalala name="Jack";surname="Smith"
pattern = re.compile(r'.*sname="([^"]*)"')
def select_rows_set():
f = open('./data.txt', 'r')
out_f = open('./data_out_set.txt', 'a')
for record in f.readlines():
name = pattern.match(record).groups()[0]
if name in name_set:
out_f.write(record)
out_f.close()
f.close()
def select_rows_dict():
f = open('./data.txt', 'r')
out_f = open('./data_out_dict.txt', 'a')
for record in f.readlines():
name = pattern.match(record).groups()[0]
if name in names_dict:
out_f.write(record)
out_f.close()
f.close()
if __name__ == '__main__':
# One round to time the use of name_set
t0 = time.time()
select_rows_set()
t1 = time.time()
time_for_set = t1-t0
print 'Total set: ', time_for_set
# One round to time the use of names_dict
t0 = time.time()
select_rows_dict()
t1 = time.time()
time_for_dict = t1-t0
print 'Total dict: ', time_for_dict
我假设Counter
本质上是字典,并且更容易从数据集构建,不会增加访问时间的任何开销。如果我遗漏了什么,很高兴得到纠正。
您的数据结构清晰地为表格,因此这可能适用。用于在内存中维护表格数据的数据结构?
您可以使用自己的"按名称搜索"功能创建自定义数据结构。那将是某种字典的列表。这应该比文本文件的大小占用更少的内存,因为它会删除您在每行上的重复信息,例如"name"和"surname",这将是字典键。如果你知道一点SQL(这里只需要很少),那么使用python过滤大文件,使用另一个的内容