【问题标题】:How do I keep the delimiters when splitting a Ruby string?拆分 Ruby 字符串时如何保留分隔符?
【发布时间】:2013-08-08 00:19:34
【问题描述】:

我有这样的文字:

content = "Do you like to code? How I love to code! I'm always coding." 

我正在尝试将其拆分为 ?.!

content.split(/[?.!]/)

当我打印出结果时,缺少标点分隔符。

你喜欢写代码

我多么喜欢编码

我一直在编码

如何保留标点符号?

【问题讨论】:

  • 所以你基本上想在每个分隔符之后放置换行符?您希望返回的实际值是多少(在 Ruby 代码中)?
  • 我不确定这对我将如何呈现数据有什么影响(即在每个分隔符后添加一个换行符)。由于split 在数组中返回结果,因此我希望数组元素中的每个句子都包含分隔符标点符号,这样当我分别打印数组元素时,它们对标点符号有意义。

标签: ruby


【解决方案1】:

回答

在括号捕获组内使用正向后向正则表达式(即?<=)以将分隔符保留在每个字符串的末尾:

content.split(/(?<=[?.!])/)

# Returns an array with:
# ["Do you like to code?", " How I love to code!", " I'm always coding."]

这会在第二个和第三个字符串的开头留下一个空格。在捕获组之后添加一个匹配零个或多个空格 (\s*) 以将其排除:

content.split(/(?<=[?.!])\s*/)

# Returns an array with:
# ["Do you like to code?", "How I love to code!", "I'm always coding."]

附加说明

虽然您的示例没有意义,但分隔符可以从第二个字符串开始移到字符串的前面。这是通过积极的前瞻正则表达式(即?=)完成的。为了任何人都在寻找这种技术,这里是如何做到的:

content.split(/(?=[?.!])/)

# Returns an array with:
# ["Do you like to code", "? How I love to code", "! I'm always coding", "."]

说明行为的更好示例是:

content = "- the - quick brown - fox jumps"
content.split(/(?=-)/)

# Returns an array with:
# ["- the ", "- quick brown ", "- fox jumps"]

请注意,方括号捕获组不是必需的,因为只有一个分隔符。此外,由于第一个匹配发生在第一个字符处,它最终成为数组中的第一项。

【讨论】:

  • @BrainLikeADullPencil 检查this link
  • 还是@content.split(/(?=\?|\.|!)/),根据你想要标记在哪一部分
  • @sawa 为什么这是一个“奇怪的要求”?这对我来说似乎很自然。我想我的意图似乎很明显,那你会怎么做?
  • 这只是主观的。我想不出有什么用。如果您可以接受除第一个以外的所有句子的前导空格,那么没关系。
  • 好的,现在我明白了。我没有意识到第一个解决方案会留下领先的空间。感谢您的帮助。
【解决方案2】:

要回答问题的标题,将捕获组添加到拆分正则表达式将保留拆分分隔符:

"Do you like to code? How I love to code! I'm always coding.".split /([?!.])/
  => ["Do you like to code", "?", " How I love to code", "!", " I'm always coding", "."]

从那里,重构句子非常简单(或根据问题要求进行其他按摩):

s.split(/([?!.])/).each_slice(2).map(&:join).map(&:strip)
 => ["Do you like to code?", "How I love to code!", "I'm always coding."]

不过,其他答案中给出的正则表达式确实更简洁地完成了问题的主体。

【讨论】:

    【解决方案3】:

    使用partition。文档中的一个示例:

    "hello".partition("l")         #=> ["he", "l", "lo"]
    

    【讨论】:

    • 这仅适用于分隔符的单个实例,或者您只关心第一个实例。根据partition 上的 Ruby 文档:“在字符串中搜索 sep 或模式(正则表达式)并返回它之前的部分、匹配项和之后的部分。如果找不到,则返回两个空字符串和 str。”所以'hellollo'.partition('l') 变成了["he", "l", "lollo"]。如果您想要所有这些,请使用 Chris Heald 的解决方案:'hellollo'.split(/(l)/) # =&gt; ["he", "l", "", "l", "o", "l", "", "l", "o"]
    【解决方案4】:

    我会使用类似的东西:

    content.scan(/.+?[?!.]/)
    # => ["Do you like to code?", " How I love to code!", " I'm always coding."]
    

    如果您想摆脱中间的空格,请使用:

    content.scan(/.+?[?!.]/).map(&:lstrip)
    # => ["Do you like to code?", "How I love to code!", "I'm always coding."]
    

    【讨论】:

      【解决方案5】:

      最可靠的方法是使用自然语言处理库:Rails gem to break a paragraph into series of sentences

      你也可以分组:

      @content.split(/(\?+)|(\.+)|(!+)/)
      

      分组后,可以加入句子和分隔符。

      @content.split(/(\?+)|(\.+)|(!+)/).each_slice(2) {|slice| puts slice.join}
      

      【讨论】:

        猜你喜欢
        • 2016-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-23
        • 1970-01-01
        • 1970-01-01
        • 2022-11-03
        • 1970-01-01
        相关资源
        最近更新 更多