我是Python的新手,尤其是处理大量数据的新手。我正在开展一个有趣的项目,这实际上是我以前用另一种语言做过的事情的高档。
现在,我正在加载一个相当大的(100mb +)文本文档,将其分解为单词,然后确定每个前缀后面的单词的频率(每个前缀是一个或多个单词)。在Python中实现相当简单和有趣,我最终得到了以下内容:
def prefix(symbols):
relationships = {}
for i in reversed(range(len(symbols))):
prefix = seperator.join(symbols[i:i+samples])
suffix = None
if i+samples < len(symbols):
suffix = symbols[i+samples]
if prefix not in relations:
relations[prefix] = {}
if suffix not in relations[prefix]:
relations[prefix][suffix] = 1
else:
relations[prefix][suffix] += 1
return relations
(函数名称,它的参数和全局“样本”的使用只是暂时的,当我解决问题时)
这很有效,大约需要20秒左右才能处理来自维基百科的60mb明文文章。然而,将样本大小(“样本”变量)从1增加到甚至4或5会大大增加内存使用量(正如预期的那样 - 大约有1000万个单词,对于每个单词,“样本”很多单词被切片并加入到一个新的字符串)。这很快就会接近并达到2千兆字节的内存限制。
我用来缓解这个问题的一种方法是在迭代时从内存中删除初始单词,因为它们不再需要(单词列表可以简单地构造为函数的一部分,所以我不是修改传入的任何内容。)
def prefix(symbols):
relationships = {}
n = len(symbols)
for i in range(n):
prefix = seperator.join(symbols[0:samples])
suffix = None
if samples < len(symbols):
suffix = symbols[samples]
if prefix not in relationships:
relationships[prefix] = {}
if suffix not in relationships[prefix]:
relationships[prefix][suffix] = 1
else:
relationships[prefix][suffix] += 1
del symbols[0]
return relationships
这确实有帮助,但不是很多,而是以某种表现为代价。
所以我要问的是这种方法是否相当有效或推荐,如果没有,哪种方法更合适?我可能会错过一些避免冗余创建字符串和复制列表的方法,因为大部分内容对我来说都是新的。 我在考虑:
欢呼任何建议或协助!
答案 0 :(得分:1)
在Python中使用大字符串时,如果需要进行大量更改,主要的建议是:
原因是Python中的字符串是不可变的。例如,symbols[i:i+samples]
的每个操作都会强制Python分配新内存,复制所需的字符串,并将其作为新的字符串对象返回。因此,当您需要对字符串进行许多更改(通过索引更改,拆分)时,您最好使用可变的列表。
答案 1 :(得分:0)
重新。加快这个过程,我发现使用try / except块来更新哈希表很有用。例如:
try:
relationships[prefix][suffix] += 1
except KeyError:
relationships[prefix][suffix] = 1
上述代码不会使用'in'来检查密钥,然后更新/创建需要对该密钥进行另一次检查的密钥,而是消除了一次检查,因此工作得更快。
答案 2 :(得分:0)
使用iterator_of_symbols = iter(list_of_symbols)
,然后next()
使用iterator_of_symbols.next()
了解更多Which is more efficient, a for-each loop, or an iterator?
虽然用Java解释过,但我认为概念是相同的。