【问题标题】:Ruby: Extracting Words From StringRuby:从字符串中提取单词
【发布时间】:2011-11-29 03:48:10
【问题描述】:

我正在尝试从字符串中解析单词并将它们放入数组中。我尝试了以下方法:

@string1 = "oriented design, decomposition, encapsulation, and testing. Uses "
puts @string1.scan(/\s([^\,\.\s]*)/)

它似乎可以解决问题,但有点不稳定(例如,我应该包含更多特殊字符)。在红宝石中有更好的方法吗?

可选:我有一个 cs 课程说明。我打算从中提取所有单词并将它们放在一个字符串数组中,从生成的数组中删除英语中最常见的单词,然后将其余单词用作用户可以用来搜索 cs 的标签课程。

【问题讨论】:

  • 英文很难用正则表达式解析。您是否考虑过自然语言解析器?它将更准确地识别句子 Mr. Smith is here. 中句点之间的差异,并将 Mr. 作为一个包含点的单词返回,但 here 不包含点。
  • @MarkByers,非常好,我现在没有。我会仔细看看的。谢谢!

标签: ruby-on-rails ruby regex parsing


【解决方案1】:

分割命令。

   words = @string1.split(/\W+/)

将基于正则表达式将字符串拆分为数组。 \W 表示任何“非单词”字符,“+”表示组合多个分隔符。

【讨论】:

  • 这并不总是有效。 "Café Restaurant".split(/\W+/) => ["Caf", "Restaurant"] 去掉特殊字符。
  • 数字也有问题:"8.3".split(/\W+/) => [8.3]
  • 简单地使用strip先去掉空格,所以:@string.strip.split(/\W+/)
  • 这不适用于带有“you're”和“it's”等缩略词的单词
  • @lazzy.developer 下面的答案也适用于多语言单词、特殊字符和标点符号,如本例所示:rubular.com/r/8ZfgmWP1Au
【解决方案2】:

对我来说最好的分句是:

line.split(/[^[[:word:]]]+/)

即使使用多语言单词和标点符号也能完美工作:

line = 'English words, Polski Żurek!!! crème fraîche...'
line.split(/[^[[:word:]]]+/)
=> ["English", "words", "Polski", "Żurek", "crème", "fraîche"] 

【讨论】:

  • 谢谢。适用于非拉丁词。
  • 宫缩怎么样?
  • ["can", "t"] 处理收缩
  • 不处理收缩。您可以尝试line.split(/[^[[:word:]]']+/),但所有'words' 仍然是'words'
【解决方案3】:

好吧,如果这是您感兴趣的分隔符,您可以将字符串拆分为空格

@string1.split(' ')

或者在单词边界上拆分

\W  # Any non-word character

\b  # Any word boundary character

或非文字

\s  # Any whitespace character

提示:尝试在 http://rubular.com 上测试每一个

请注意,ruby 1.9 与 1.8 有一些不同

【讨论】:

  • 如 david nehme 的回答中所述,您可能希望使用 + 运算符来指示与该模式匹配的一个或多个连续字符
  • 此外,扫描非常适合从文本中提取匹配模式,并且可以与我们上面的拆分建议相反,例如s.scan(/w+/)
  • 感谢您的许多好建议!今天早上我玩了很多rubular,它是一个了不起的教学工具。我只是在将所选模式提取到我的代码中时遇到了麻烦。 @string1.split(%r{\W+}) 似乎运作良好,但 Mark Byers(上面的评论者)对自然语言解析有一个很好的观点,所以我需要牢记这一点。无论如何,谢谢!
  • 注意 BF4 在他/她的评论中缺少反斜杠,应该是:s.scan(/\w+/)
【解决方案4】:

对于 Rails,您可以使用如下内容:

@string1.split(/\s/).delete_if(&:blank?)

【讨论】:

    【解决方案5】:

    我会这样写:

    @string
      .split(/,+|\s+/)  # any ',' or any whitespace characters(space, tab, newline)
      .reject(&:empty?)
      .map { |w| w.gsub(/\W+$|^\W+^*/, '') } # \W+$ => any trailing punctuation; ^\W+^* => any leading punctuation
    
    irb(main):047:0> @string1 = "oriented design, 'with', !!qwe,  and testing. can't rubyisgood#)(*#%)(*, and,rails,is,good"
    => "oriented design, 'with', !!qwe,  and testing. can't rubyisgood#)(*#%)(*, and,rails,is,good"
    irb(main):048:0> @string1.split(/,+|\s+/).reject(&:empty?).map { |w| w.gsub(/\W+$|^\W+^*/, '')}
    => ["oriented", "design", "with", "qwe", "and", "testing", "can't", "rubyisgood", "and", "rails", "is", "good"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-27
      • 2023-04-03
      • 2017-02-14
      • 2021-03-15
      • 2012-10-27
      相关资源
      最近更新 更多