更好的正则表达式在红宝石中分裂句子?

时间:2011-12-02 03:52:24

标签: ruby regex arrays pattern-matching

我正在研究一个单词出现在一堆文本中的频率,告诉它出现在哪个句子中,然后按每个单词的频率对结果进行排序。例如: sample input and out put

这就是我到目前为止所做的:

File.open('sample_text.txt', 'r') do |f| # open a file named "sample_text.txt"

content = f.read # turn the content into a long string

# split the string by sentences
sentences = content.split(/\.|\?|\!/).each do |es|

  es.split(/\W|\s/).each do |w| 
     #split into individual words 
     #and for each word, find matched words in the content

  end

end
end

问题:

1 分裂句子有更好的正则表达式吗?现在,split(/\.|\?|\!/)web 2.0作为两句话web 20

2 任何人都可以给我一些关于如何处理返回一个单词所在句子的部分的提示吗?

4 个答案:

答案 0 :(得分:1)

  1. 如何在句点之后(或?!之类的标点符号)要求空格,然后可选地阻止其前面有某些众所周知的缩写(例如{{1} }或vs.Mr.Mrs.i.e.),或许可能要求之后有大写字母?

  2. 给定一个句子字符串数组和一个将每个句子分成一个单词数组的方法(我会把它留给你),你可以这样做:

    e.g.

答案 1 :(得分:1)

这是一个完整的工作样本

require 'pp'
content = "Meet Mr. Jon. Jon is a computer programmer and lives in Connecticut. Jon is tall. Shouldn't take web 2.0 as two sentences. And this is a new sentence. "
words = {}
content.gsub!(/(Mr)\.|(Mrs)\./,"\\1{dot}").split(/\. |\? |\! /).each_with_index do |sentences, index|
  puts "\n#{index}: #{sentences}"
  sentences.split(/ +/).each do |word|
    word=word.gsub(/{dot}/,"\.").downcase
    puts word
    words[word]=words[word]||[0,[]]
    words[word][0]+=1
    words[word][1]<<index
  end
end
pp words

最后一页给出了

{"meet"=>[1, [0]],
 "mr."=>[1, [0]],
 "jon"=>[3, [0, 1, 2]],
 "is"=>[3, [1, 2, 4]],
 "a"=>[2, [1, 4]],
 "computer"=>[1, [1]],
 "programmer"=>[1, [1]],
 "and"=>[2, [1, 4]],
 "lives"=>[1, [1]],
 "in"=>[1, [1]],
 "connecticut"=>[1, [1]],
 "tall"=>[1, [2]],
 "shouldn't"=>[1, [3]],
 "take"=>[1, [3]],
 "web"=>[1, [3]],
 "2.0"=>[1, [3]],
 "as"=>[1, [3]],
 "two"=>[1, [3]],
 "sentences"=>[1, [3]],
 "this"=>[1, [4]],
 "new"=>[1, [4]],
 "sentence"=>[1, [4]]}

您可以根据将它们放在黑名单上的最小长度来过滤掉“a”之类的字词。 好奇你正在做什么,我正在构建一个wiki的索引器,因为我无法在我的windows / ruby​​上运行Xapian。 Grtz

答案 2 :(得分:0)

您可以通过添加正向预测断言来提高正则表达式

(?:\.|\?|\!)(?= [^a-z]|$)

here on Regexr

(?= [^a-z]|$)是一个积极的loookahead,用于检查是否有空格后跟非小写字母或前面字符串的结尾。这给匹配带来了很好的改善。

Phrogz的另一个建议(防止在常见的appreviations上匹配)在一步中不可能在正则表达式中,因为Ruby不支持lookbehind断言。

需要更多步骤来实现这一目标的可能性是在第一步中搜索那些应用程序并用占位符替换它们(例如先生与#DOT先生#),然后在分开点后再次替换占位符。

只是为了好玩,不使用Ruby!版本背后的外观:

(?<!\be\.g|\bi\.e|\bvs|\bMr|\bMrs|\bDr)(?:\.|\?|\!)(?= |$)

here on Regexr

答案 3 :(得分:0)

使用单词boundary matcher:str.split(/ \ W + /)。它适用于大多数文本(虽然我猜它会分开'字符)。