【问题标题】:How to remove all words in a list from a fixed list of candidates?如何从固定的候选列表中删除列表中的所有单词?
【发布时间】:2014-08-16 06:50:20
【问题描述】:

我正在编写包含综合文本预处理的代码,包括停用词删除、词干提取、样板信息删除/替换(网址、电子邮件、数字、金额、标签等)、构建倒排索引、LCA等等。这不足为奇 - 删除停用词是瓶颈,也是该过程中最昂贵的部分。

我现在拥有的很简单:

我在静态数组static const std::wstring stopwords [] 中存储了大约 500 个停用词。

然后对于每个文档 (std::vector<wstring>):

for each ( auto term in stopwords)
{
    doc.erase( std::remove( doc.begin(), doc.end(), term), doc.end() );
}

有什么建议可以提高这段代码的性能吗?

【问题讨论】:

  • 使用 remove_if 和 lambda 一次检查所有单词
  • quantdev,“一次检查所有单词”是什么意思?您能否扩展和/或提供示例和/或解释为什么它会更快?谢谢
  • downvoter 可以解释一下吗?在我看来这是一个合理的问题!
  • @user2028058 这意味着将您的停用词存储在一个有效的可搜索容器中,然后枚举 document (不是停用词),以及文档中的每个单词,如果它在停用词容器中,将其删除。这就是 std::remove_if 的目的。阅读 Gabe 的回答,了解为什么这样做会更有效率。

标签: c++ text vector stop-words


【解决方案1】:

您的算法是 n*m,多次搜索文档。相反,您应该遍历 doc 中的单词,检查每个单词是否是停用词,并且您的停用词应该在哈希表(而不是映射)中,以便您可以执行 O(1) 检查给定单词是否是停用词。这会将您的时间减少到 O(n),其中 n 是文档的大小。

例如:C++11 提供了一个可用于哈希表的无序集合容器。

std::unordered_set<std::wstring> stopwords; // keep your stop words in here.

一旦你有了这个,简单的解决方案就变成了:

doc.erase(std::remove_if(
    doc.begin(),
    doc.end(),
    [](const std::wstring& s){ return stopwords.find(s) != stopwords.end(); }),
    doc.end());

不经受大小写敏感性检查(您的原始样本没有考虑,所以我们也没有在这里),这将比您以前的表现显着更好,假设你的话有合理的哈希分布。

【讨论】:

  • 太棒了!这就像一个魅力,极大地提高了性能。非常好的建议,谢谢大家
猜你喜欢
  • 2018-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-13
  • 2021-12-29
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多