找出大型列表中的哪些单词出现在一个小字符串中

时间:2011-02-01 06:45:42

标签: ruby regex

我有一个静态的'大'单词列表,大约300-500个单词,名为'list1'

给出一个约40个单词的相对较短的字符串str,这是ruby中最快的方法:

  1. list1str中的单词出现的次数(计算多次出现次数)
  2. list1中的单词在字符串str
  3. 中出现一次或多次的列表
  4. (2)
  5. 中的字数

    str中的'Occuring'表示str中的整个单词,或str中单词中的部分单词。因此,如果'fred'位于list1str包含'fred''freddie',那么这将是两场比赛。

    一切都是小写的,所以任何匹配都不必关心案例。

    例如:

    list1 ="fred sam sandy jack sue bill"
    str = "and so sammy went with jack to see fred and freddie"
    

    所以str包含samjackfred(两次)

    对于部分(1),表达式将返回4(sam + jack + fred + fred)
    对于第(2)部分,表达式将返回“sam jack fred”
    第(3)部分是3

    执行此操作的'红宝石方式'在4小时后躲过我...迭代它很容易(但很慢)。任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:2)

以下是我拍摄的照片:

def match_freq(exprs, strings)
  rs, ss, f = exprs.split.map{|x|Regexp.new(x)}, strings.split, {}
  rs.each{|r| ss.each{|s| f[r] = f[r] ? f[r]+1 : 1 if s=~r}}
  [f.values.inject(0){|a,x|a+x}, f, f.size]
end

list1 = "fred sam sandy jack sue bill"
str = "and so sammy went with jack to see fred and freddie"
x = match_freq(list1, str)
x # => [4, {/sam/=>1, /fred/=>2, /jack/=>1}, 3]

“match_freq”的输出是输出项目(a,b,c)的数组。算法本身是O(n*m),其中n是list1中的项目数,m是输入字符串的大小,我认为你不能做得更好(用语言来说)大哦)。但是有一些较小的优化可能会有所回报,例如为匹配总数保留一个单独的计数器而不是之后计算它。这只是我对它的快速破解。

您可以从输出中提取匹配的单词,如下所示:

matches = x[1].keys.map{|x|x.source}.join(" ") # => "sam fred jack"

请注意,订单不会被保留,如果重要的话,您必须保留单独的订单列表。

答案 1 :(得分:2)

这是一个替代实现,用于您的启发:

def match_freq( words, str )
  words  = words.split(/\s+/)
  counts = Hash[ words.map{ |w| [w,str.scan(w).length] } ]
  counts.delete_if{ |word,ct| ct==0 }
  occurring_words = counts.keys
  [
    counts.values.inject(0){ |sum,ct| sum+ct }, # Sum of counts
    occurring_words,
    occurring_words.length
  ]
end

list1 = "fred sam sandy jack sue bill"
str   = "and so sammy went with jack to see fred and freddie"
x     = match_freq(list1, str)
p x   #=> [4, ["fred", "sam", "jack"], 3]

请注意,如果我需要这些数据,我可能只是从方法中返回'counts'哈希值,然后根据需要进行任何分析。如果我要从分析方法返回多个'值',我可能会返回一个命名值的哈希值。虽然,返回一个数组允许你取消结果:

hits, words, word_count = match_freq(list1, str)
p hits, words, word_count  
#=> 4
#=> ["fred", "sam", "jack"]
#=> 3

答案 2 :(得分:0)

对于更快的正则表达式,请使用https://github.com/mudge/re2。它是 Google re2 https://code.google.com/p/re2/

的红宝石包装