将字符串拆分为列表,但保持拆分模式

Her*_*son 14 ruby string split

目前我按模式拆分字符串,如下所示:

outcome_array=the_text.split(pattern_to_split_by)
Run Code Online (Sandbox Code Playgroud)

问题是我分裂的模式本身总是被省略.

如何让它包含拆分模式本身?

Dav*_*son 26

感谢Mark Wilkins的不满,但这里有一小段代码:

irb(main):015:0> s = "split on the word on okay?"
=> "split on the word on okay?"
irb(main):016:0> b=[]; s.split(/(on)/).each_slice(2) { |s| b << s.join }; b
=> ["split on", " the word on", " okay?"]
Run Code Online (Sandbox Code Playgroud)

要么:

s.split(/(on)/).each_slice(2).map(&:join)
Run Code Online (Sandbox Code Playgroud)

请参阅下面的折叠以获得解释.


这是如何工作的.首先,我们将其分为"on",但将其包含在括号中以使其成为匹配组.当传递给正则表达式的匹配组时split,Ruby将在输出中包含该组:

s.split(/(on)/)
# => ["split", "on", "the word", "on", "okay?"
Run Code Online (Sandbox Code Playgroud)

现在我们想要将"on"的每个实例与前面的字符串连接起来. each_slice(2)通过一次将两个元素传递给它的块来帮助.我们只是调用each_slice(2)以查看结果.因为each_slice,在没有块的情况下调用时,将返回枚举器,我们将应用于to_a枚举器,以便我们可以看到枚举器将枚举的内容:

s.split(/(on)/).each_slice(2).to_a
# => [["split", "on"], ["the word", "on"], ["okay?"]]
Run Code Online (Sandbox Code Playgroud)

我们越来越近了.现在我们所要做的就是将这些词汇合在一起.这让我们得到了上面的完整解决方案.我将它打开成单独的行,以便更容易理解:

b = []
s.split(/(on)/).each_slice(2) do |s|
  b << s.join
end
b
# => ["split on", "the word on" "okay?"]
Run Code Online (Sandbox Code Playgroud)

但是有一种很好的方法来消除临时b代码并大大缩短代码:

s.split(/(on)/).each_slice(2).map do |a|
  a.join
end
Run Code Online (Sandbox Code Playgroud)

map将其输入数组的每个元素传递给块; 块的结果成为输出数组中该位置的新元素.在MRI> = 1.8.7中,您可以将其缩短到相当于:

s.split(/(on)/).each_slice(2).map(&:join)
Run Code Online (Sandbox Code Playgroud)

  • +1非常好.我喜欢Ruby; 它具有简洁但可读的语法. (2认同)

小智 6

您可以使用正则表达式断言来定位分割点而不消耗任何输入.下面使用正面的后视断言在'on'之后拆分:

s = "split on the word on okay?"
s.split(/(?<=on)/)
=> ["split on", " the word on", " okay?"]
Run Code Online (Sandbox Code Playgroud)

或者在"开启"之前进行正面预测:

s = "split on the word on okay?"
s.split(/(?=on)/)
=> ["split ", "on the word ", "on okay?"]
Run Code Online (Sandbox Code Playgroud)

有了这样的东西,你可能想确保'on'不是一个更大的单词的一部分(比如'assertion'),并且还要删除分割处的空格:

"don't split on assertion".split(/(?<=\bon\b)\s*/)
=> ["don't split on", "assertion"]
Run Code Online (Sandbox Code Playgroud)