【问题标题】:How to efficiently check text against a word list in Ruby?如何根据 Ruby 中的单词列表有效地检查文本?
【发布时间】:2015-05-28 00:56:27
【问题描述】:

给定 1,000 个单词的文本,对照 10,000 个单词的字典检查的有效方法是什么?我想计算非唯一匹配的数量。

一个想法是将字典存储为哈希。但随后我必须根据哈希检查每个单词,这将是 1,000 次操作。这似乎效率不高。

另一个想法是 Postgres 文本搜索。但是是否可以在一个查询中执行此检查?

另一个想法是将单词存储在 Memcache 或 Redis 数据库中,但这需要 1,000 次查询并且非常慢。

那么,有没有更有效的解决方案?

在 Ruby 中工作。

编辑:为 a 添加基准:

Cary 关于dict_set 更快的断言是正确的:

aw.length
=> 250
dw.length
=> 1233
dict_set.length
=> 1223
t = Time.now; 1000.times{ aw & dw }; Time.now - t
=> 0.682465
t = Time.now; 1000.times{ aw.count{ |w| dict_set.include? w }}; Time.now - t
=> 0.063375

所以,Set#include? 似乎很有效。

【问题讨论】:

  • 您想只执行一次还是针对 1,000 个单词的多个文本(使用同一个词典)执行此操作? “非唯一”匹配是什么意思?
  • 1000字集排序了吗?
  • @HenryChinner - 是的,1000字集可以排序。
  • @CarySwoveland - 是的,我想根据同一个词典检查许多 1,000 个单词的文本。通过非唯一,我的意思是假设“真棒”这个词在文本中出现了两次。如果它出现在字典中,则找到的字数将增加 2。
  • 如果“awesome”在文本中只出现一次并且在字典中,计数是加0还是加1?

标签: ruby algorithm text


【解决方案1】:

假设:

text = "The quick brown fox and the quick brown bear jumped over the lazy dog"

dictionary = ["dog", "lazy", "quick", "sloth", "the"]

让我们首先将dictionary 转换为一个集合:

require 'set'
dict_set = dictionary.to_set
  #=> #<Set: {"dog", "lazy", "quick", "sloth", "the"}>

并将text 转换为一个小写单词数组:

words = text.downcase.split
  #=> ["the", "quick", "brown", "fox", "the", "and", "quick",
  #    "brown", "bear", "jumped", "over", "the", "lazy", "dog"]

以下是计算textdictionary 中单词数量的几种方法。

#1:简单计数

words.count { |w| dict_set.include?(w) }
  #=> 7

#2:将相同的单词分组并计数

words.group_by(&:itself).reduce(0) { |tot,(k,v)|
  tot + ((dict_set.include?(k)) ? v.size : 0) }  
  #=> 7

Object#itself 在 v2.2 中引入。对于早期版本,请替换:

group_by(&:itself)

group_by { |w| w }

步骤:

h = words.group_by(&:itself)
  #=> {"the"  =>["the", "the", "the"],
  #    "quick"=>["quick", "quick"],
  #    "brown"=>["brown", "brown"],
  #    "fox"=>["fox"],
  #    ...
  #    "dog"=>["dog"]} 
h.reduce(0) { |tot,(k,v)| tot + ((dict_set.include?(k)) ? v.size : 0) }
  #=> 7}

考虑到Set#include? 非常快,我预计#1 通常最快。也就是说,我怀疑对相同单词进行分组的时间少于在字典查找中节省的时间。

【讨论】:

  • 太棒了!我不知道&amp; 会这样做。
  • 嘿,&amp; 怎么了?
  • t&amp;d 对于t 的每个元素有效地逐步遍历d 的每个元素。如果你只做一次没关系,但如果你为不同的t 和相同的d 多次这样做,效率就会很低。在这种情况下,首先将 d 转换为一个集合(这是通过哈希在幕后完成的)效率更高,因为集合查找非常快。
  • 我收到undefined method `itself' for "A":String。您使用的是哪个版本的 Ruby?
  • 请看我的编辑。我本来想提早一点的,但忘了提。
猜你喜欢
  • 1970-01-01
  • 2015-07-14
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多