在大文件中最省时的搜索 - 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),所有内容都在字典和测试中...... “大”有多大? 当你做测试时,记得测试fgrepfgrep 将 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的主要内容,如果未能解决你的问题,请参考以下文章

python 在大文件里面删除某一行,比较有效率的方法

在大文本文件中查找文本数据的快速方法是啥?

仅在大括号外替换文件中的字符串

在大括号之间搜索和替换文本(VS代码)

HDFS 为何在大数据领域经久不衰?

HDFS 为何在大数据领域经久不衰?