在大文件中最省时的搜索 - Python
Posted
技术标签:
【中文标题】在大文件中最省时的搜索 - Python【英文标题】:Most time efficient search in a large file - Python 【发布时间】:2017-07-07 03:20:57 【问题描述】:我正在大文本文件中搜索匹配项,但我发现它太慢了。这是文件结构:
word1 5752
word2 96332
word3 137
我正在尝试匹配第一列中的文本,并且我想提取第二列中的值。列由 \t 分隔,大约有 1000 万行。使用不同的词多次搜索该文件。哪种搜索方法的时间效率最高?
编辑:该文件为 129 Mb,至少会被搜索数千次。 EDIT2:文件按字母顺序排序,只有当它们具有不同的大写字母时,单词才能出现多次,例如:Word WORD word WOrd 将都是不同的条目。
【问题讨论】:
您如何搜索,如何加载数据?例如,如果您将整个文件加载到内存中,那么这可能是性能不佳的原因。或者,使用不同的算法可能会更好,您可以在再次阅读之前搜索每行的不同单词吗? 根据您搜索数据的次数,您可以将整个文件加载到内存中并将其转换为字典。虽然这可能会消耗一些内存。 "什么搜索方法的时间效率最好?" — “这取决于” — 这取决于您的机器有多少内存、单词的长度、word1
是否有可能在文件中有多个实例,其他我忘记提及的事情。总而言之,我会接受voidpointercast 的建议(现在已升级为answer),所有内容都在字典和测试中......
“大”有多大?
当你做测试时,记得测试fgrep
— fgrep
将 PATTERN 解释为固定字符串列表(而不是正则表达式),用换行符分隔,其中任何一个都是匹配。
【参考方案1】:
with open('myfile.dat','r') as src:
mapping = dict((line.strip().split('\t') for line in src if line))
根据文件和内存的大小,这可能是一个解决方案。如果您在程序运行期间必须多次执行这种搜索算法。
【讨论】:
该文件为129 Mb,将被搜索成千上万次。所以我猜内存要求不是很高,我对时间效率更感兴趣。 从字典键中获取值应该是相当有效的。我猜它们是使用二叉树实现的,但我不确定。【参考方案2】:如果您将数据存储在哈希表(python 字典结构)中,执行此操作会非常快。您的“键”是名称,每个键都有一个“值”,即数字。下面显示的这段代码利用散列来更快地检索数据:
yourDict = 'name0':number0,'name1':number1,...,'nameN':numberN
if 'checkName' in yourDict:
#It exists!
theNumber = yourDict['checkName']
else:
#It doesn't exist :/
*注意:如果你使用:
if 'checkName' in yourDict.keys():
您实际上是在创建一个键列表,然后搜索它们。此操作不使用哈希表(慢得多)。
这是关于 HandTable 数据结构如何工作的一点: https://www.youtube.com/watch?v=MfhjkfocRR0
这是一个答案,表明 python 中的字典就像一个哈希表: Is a Python dictionary an example of a hash table?
【讨论】:
怎么样:theNumber = yourDict.get('checkName')?如果值不存在,theNumber 将为无。关于性能的任何见解? 我刚刚查了一下,看来您是对的!这对我来说似乎有点违反直觉,但是这个人在非常大的文件上对其进行了测试,并得到了显着的改进。所以代码应该是:yourDict.get('checkName') partofthething.com/thoughts/?p=513【参考方案3】:这是作业还是工作/项目?我不知道人们对重新实现核心算法有何感受,但你的文本文件有多大?
一种使用 Pandas 的替代方法以实现易用性和底层优化:
In [61]: df = pd.read_csv(r'C:\temp\data.txt', header=None, sep=' ')
In [62]: df
Out[62]:
0 1
0 word1 5752
1 word2 96332
2 word3 137
In [63]: df[df[0] == 'word2']
Out[63]:
0 1
1 word2 96332
In [64]: df[df[0] == 'word2'][1]
Out[64]:
1 96332
Name: 1, dtype: int64
2 个问题:
1) 可以将其保存在内存中而不是每次都重新加载吗? (也许 TTL 大约一个小时?)
2) 您的文件是否已排序?我相信二进制搜索需要首先对数据进行排序。每次必须读取数据时进行排序对性能有何影响?
【讨论】:
1.它可以保存在内存中,当然 2. 已排序 如果你能把它保存在内存中,那么你如何读它就变得不那么重要了。我认为您的最佳性能将来自于将其留在数据框中并仅对其进行查询。【参考方案4】:我会先按字母顺序对文件进行排序,然后执行对数搜索 (https://en.wikipedia.org/wiki/Binary_search_algorithm)。 你有一个很好的例子来说明如何在这里用 python 做到这一点: http://programarcadegames.com/index.php?chapter=searching&lang=en#section_16.5
【讨论】:
如果文件被程序的多次运行“触及”,这是一种很好的方法。以上是关于在大文件中最省时的搜索 - Python的主要内容,如果未能解决你的问题,请参考以下文章