Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
查找大型列表是否包含特定字符串的最有效方法(Python)_Python_String - Fatal编程技术网

查找大型列表是否包含特定字符串的最有效方法(Python)

查找大型列表是否包含特定字符串的最有效方法(Python),python,string,Python,String,我有一个文件,包含了大约所有的英文单词(~60k单词,~500k字符)。我想测试输入的某个单词是否为“英语”(即,该单词是否在列表中) 在Python中,最有效的方法是什么 简单的解决方案是将文件加载到列表中,并检查单词是否在该列表中。该列表可以排序,我相信这将把复杂性缩减为O(logn)。但是,我不确定Python如何实现列表搜索,以及如果内存中有这么大的列表,是否会有性能损失。我可以“滥用”我可以限制字数的事实吗?(例如,假设最长的长度为15个字符) 请注意,我在一台有大量内存的机器上运行应

我有一个文件,包含了大约所有的英文单词(~60k单词,~500k字符)。我想测试输入的某个单词是否为“英语”(即,该单词是否在列表中)

在Python中,最有效的方法是什么

简单的解决方案是将文件加载到列表中,并检查单词是否在该列表中。该列表可以排序,我相信这将把复杂性缩减为O(logn)。但是,我不确定Python如何实现列表搜索,以及如果内存中有这么大的列表,是否会有性能损失。我可以“滥用”我可以限制字数的事实吗?(例如,假设最长的长度为15个字符)

请注意,我在一台有大量内存的机器上运行应用程序,因此我关心的不是内存消耗,而是速度和CPU利用率


谢谢

你基本上是在测试一个成员是否在一个集合中,对吗

如果是这样,而且因为你说你有很多内存,为什么不把所有的单词作为键加载到memcache中,然后检查每个单词是否存在于memcache中

或者使用bash用来自动完成命令名的数据结构—这在内存中既快速又高效(记不住名称)。

python是您应该尝试的

集合对象是不同的散列对象的无序集合。常见用途包括成员资格测试,从序列中删除重复项,以及计算数学运算,如交集、并集、差分和对称差分


一个结构会适合你的目的。毫无疑问,在那里可以找到一些Python实现…

如果内存消耗不是问题,而且单词不会改变,那么最快的方法就是将所有内容放入哈希中,并以这种方式进行搜索。在Python中,这是。您将进行固定时间查找。

500k字符不是一个大列表。如果列表中的项目是唯一的,并且您需要重复执行此搜索,则最好使用将复杂性降低到
O(1)

示例Python代码:

L = ['foo', 'bar', 'baz'] # Your list
s = set(L)  # Converted to Set

print 'foo'  in s # True
print 'blah' in s # False
两件事:

Python的'mutable set'类型有一个'add'方法(s.add(item)),因此您可以直接从大文件中读取(一行)到集合中,而不使用列表作为中间数据结构

Python允许您“pickle”数据结构,这样您就可以将大型集合保存到文件中,并节省重新初始化集合的时间


第二,我一直在寻找一份英语中所有单音节单词的列表,以供自己消遣,但我发现上面提到的那些单词似乎是专有的。如果不是侵入性的,我可以问一下其他人是否可以获取您的英语单词列表吗?

只有在您对数据重复运行此类查询时,才能将列表转换为集合,排序列表和进行二进制搜索也是如此。如果您只想从列表中提取一次数据,那么简单的线性搜索是您的最佳选择:

if 'foo' in some_list:
    do_something()
否则,最好使用前面提到的集合或二进制搜索。您应该选择哪一个在很大程度上取决于数据有多大以及您可以节省多少内存。有人告诉我,真正大的列表往往从哈希中受益更多,尽管占用的内存量可能会非常昂贵


最后,第三个选项是可以将数据导入sqlite数据库并直接从中读取。Sqlite速度非常快,它可以为您节省从文件加载整个列表的麻烦。Python具有非常好的内置功能。

其他人使用set()为您提供了内存方式,这通常是最快的方式,并且不应该为60k字数据集(最多几个MIB)占用内存。您应该能够使用以下内容构建集合:

f=open('words.txt')
s = set(word.strip() for word in f)
但是,将集合加载到内存中确实需要一些时间。如果你正在检查大量的单词,这是没有问题的-查找时间将超过弥补它。但是,如果每次执行命令时只检查一个单词(例如,这是一个类似“checkenglish[word]”的命令行应用程序),则启动时间将比您逐行搜索文件所需的时间更长

如果这是您的情况,或者您有一个更大的数据集,使用磁盘格式可能会更好。最简单的方法是使用模块。从具有以下内容的单词列表创建这样的数据库:

import dbm
f=open('wordlist.txt')
db = dbm.open('words.db','c')
for word in f:
    db[word] = '1'
f.close()
db.close()
然后,您的计划可以通过以下方式检查会员资格:

db = dbm.open('words.db','r')
if db.has_key(word):
    print "%s is english" % word
else:
    print "%s is not english" % word
这将比集合查找慢,因为将有磁盘访问,但比搜索快,内存使用率低,并且没有明显的初始化时间


还有其他选择,例如使用SQL数据库(例如sqlite)。

确切地说,集合是使用哈希表构建的-因此O(1)+1,但我会提出一个古老的观点:哈希表中的查找不是真正的O(1)--如果(a)数据集足够小,并且(b)没有存储产生O(1)的一组键,那么它只是O(1)(n) (类似链表的)查找时间。实际上,(b)几乎从未违反,但许多实现违反(a)通过根据哈希表中存储的元素数量调整存储桶的数量。但是,不管实际的时间复杂度如何,哈希表在您的情况下应该可以很好地工作。Python在其整个实现过程中广泛使用哈希表(所有类成员、模块等)。在python中,几乎所有内容都存储在哈希表中,因此,您会发现python哈希表实现是最好、最高效的实现之一,至少在“日常使用”方面,我的印象是集合是用平衡树实现的,而不是哈希(这意味着O(logn)查找).这不是吗?您甚至不需要.add()。set使用迭代器作为参数,因此假设