2011-02-01 47 views
4

我有話的靜態「大」名單,大約300-500字,叫給出的約40相對較短的字符串str「列表1」找出其中的大名單的話會發生在一個小串

換句話說,什麼是紅寶石最快的方法獲取:

  1. list1一個字出現在str(計數多次出現)
  2. 哪些詞在list1發生一次或多次列表的次數字符串str
  3. 在(2)

「發生的歷史」的單詞中str裝置的數量無論是作爲在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 +插孔+ fred的+ fred的)
(2)表達式將返回「sam jack fred」
並且部分(3)是3

'r '這樣做'這樣做後4小時避開我......迭代很容易(但很慢)。任何幫助,將不勝感激!

回答

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是項目的列表1中的數量和m是輸入字符串的大小,我不認爲你可以做得比這更好的(在以下方面大哦)。但是有一些較小的優化可能會得到回報,比如爲總的匹配數保留一個單獨的計數器,而不是之後進行計算。這只是我的快速入侵。

可以按如下方式提取剛剛從輸出匹配的話:

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

注意,訂單不會必然保存,如果你要保持這個順序的單獨列表是非常重要的他們被發現。

+0

我會死。哇。你搖滾。我花了一段時間在irb上一步一步地穿過它,但這非常酷。我也不知道如何從一個函數返回多個值,所以這也是一個有用的珍聞! – jpwynn 2011-02-01 08:22:06

+0

從{/ sam/=> 1,/ fred/=> 2,/ jack/=> 1}提取「sam fred jack」最簡單的方法是什麼? – jpwynn 2011-02-01 08:26:15

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] 

需要注意的是,如果我需要這個數據,我可能只是從方法返回「計數」散,然後做任何的分析,我想就可以了。如果我要從分析方法中返回多個「值」,我可能會返回一個哈希的命名值。雖然返回一個數組可以讓你unsplat結果:

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