2012-05-26 68 views
0

組:掃描的給定輸入連續字

str = "foo bar jim jam. jar jee joon." 

我需要由空格分隔所有2-和3-字詞組的輸出:

[ "foo bar", "bar jim", "jim jam", "jar jee", "jee joon", 
    "foo bar jim", "bar jim jam", "jar jee joon" ] 

注意特別是由於期限的原因,缺少上述的「果醬罐」,「吉姆果醬罐」和「果醬罐吉」。我不能使用str.scan(/\w+/).each_cons(2).map{ |a| a.join(' ') },因爲那將包括"jam jar"

掃描/\w+ \w+/產生["foo bar", "jim jam", "jar jee"],特別缺少「bar jim」和「jee joon」,並強調了該問題。

真實世界的應用程序正在爲搜索引擎生成一個基於短語的索引。我希望找到所有真正連續的單詞作爲短語,不包括那些標點符號分開的單詞。

編輯:好像有可能是一種方式,正則表達式來做到這一點/經上的變化掃描:

"a b c d".scan(/(?=([abc] [abc]))[abc]/) 
#=> [["a b"], ["b c"]] 
+1

爲什麼不分裂'str'成句子,並單獨進行掃描嗎? –

+0

@mu因爲我以前沒有想過。我現在要走這條路。 – Phrogz

+0

我想你陷入了「我只有一​​把錘子」的陷阱:) –

回答

1

我相信這樣做的工作,雖然它假定唯一的標點符號是在週期的形式:

str.split(".").map do |s| 
    pairs_and_triples = [] 
    s.split.each_cons(2){ |*words| pairs_and_triples << words.join(" ") } 
    s.split.each_cons(3){ |*words| pairs_and_triples << words.join(" ")} 
    pairs_and_triples 
end.flatten 

編輯或者少一點repitition:

str.split(".").map do |s| 
    [2,3].map do |i| 
    s.split.each_cons(i).map{ |*words| words.join(" ") } 
    end.flatten 
end.flatten 
+0

請注意,從Ruby 1.9.2+開始,您可以使用'a = b.flat_map {...}'而不是'a = b.map {...} .flatten'。我已經給你接受,因爲它的核心與我最終做的事情相匹配。 (請參閱我的答案,使用正則表達式來捕獲代碼以定義句子邊界並僅將每個句子分開一次單詞。) – Phrogz

1
str = "foo bar jim jam. jar jee joon." 
arr = str.split(' ').each_cons(2).map do |a| 
    a.join(' ') if a.join(' ').match(/\w+ \w+/) 
end 
p arr.compact 
#=> ["foo bar", "bar jim", "jim jam.", "jar jee", "jee joon."] 

編輯:看來你已經改變了你的問題要問也適用於3個詞的短語。 ಠ_ಠ

+0

我沒有改變這個方面,但任何適用於其中的解決方案都應該能夠爲2-n(獨立)工作,並且可以在稍後進行連接。 – Phrogz

+0

好吧,如果你只是在尋找2個單詞的短語,你應該可以用'each_cons(x)'替換'each_cons(2)',並將正則表達式改爲X個單詞。 – Kerrick

0

的強大,高效的解決方案,我最終得到的是@ muistooshort建議並由@ChrisRice繪製的解決方案:

  1. 分割上句子邊界
  2. 掃描單詞(忽略無趣標點符號等逗號)
  3. 使用each_cons處理該陣列

上變化在代碼:

max_words_per_phrase = 5 
str = "foo bar, jim jam. jar: jee joon." 

phrases = str.split(/[.!?]+/).flat_map do |sentence| 
    words = sentence.scan(/\w+/) 
    2.upto(max_words_per_phrase).flat_map do |i| 
    words.each_cons(i).map{ |a| a.join(' ') } 
    end 
end 

p phrases 
#=> ["foo bar", "bar jim", "jim jam", "foo bar jim", "bar jim jam", 
#=> "foo bar jim jam", "jar jee", "jee joon", "jar jee joon"] 
0

中取出後標點符號:

str = "foo bar jim jam jar jee joon" 

當你在你的問題建議,積極先行,可以使用:

r2 = /(\w+)(?=(\s+\w+))/ 
r3 = /(\w+)(?=(\s+\w+)(\s+\w+))/ 
str.scan(r2).concat(str.scan(r3)).map(&:join) 
    #=> ["foo bar", "bar jim", "jim jam", "jam jar", "jar jee", "jee joon", 
    # "foo bar jim", "bar jim jam", "jim jam jar", "jam jar jee", "jar jee joon"]