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」と「jeejoon」が欠落し、問題が浮き彫りになります。

このための実際のアプリケーションは、検索エンジンのフレーズベースのインデックスを生成することです。句読点で区切られた単語を除いて、すべての真に連続した単語をフレーズとして見つけたいと思います。

編集:次のバリエーションを介して正規表現/スキャンでこれを行う方法があるようです:

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

4 に答える 4

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語のフレーズも要求するように質問を変更したようです。ಠ_ಠ</p>

于 2012-05-26T03:12:56.270 に答える
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

編集または少し少ない繰り返しで:

str.split(".").map do |s|
  [2,3].map do |i|
    s.split.each_cons(i).map{ |*words| words.join(" ") }
  end.flatten
end.flatten
于 2012-05-26T03:50:31.323 に答える
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"]
于 2012-05-31T21:31:42.783 に答える
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"] 
于 2015-12-20T05:46:01.440 に答える