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

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

outcome_array=the_text.split(pattern_to_split_by) 

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

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

感谢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?"] 

要么:

 s.split(/(on)/).each_slice(2).map(&:join) 

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


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

 s.split(/(on)/) # => ["split", "on", "the word", "on", "okay?" 

现在我们想要将“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?"]] 

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

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

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

 s.split(/(on)/).each_slice(2).map do |a| a.join end 

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

 s.split(/(on)/).each_slice(2).map(&:join) 

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

 s = "split on the word on okay?" s.split(/(?<=on)/) => ["split on", " the word on", " okay?"] 

或者在“开启”之前进行正向预测:

 s = "split on the word on okay?" s.split(/(?=on)/) => ["split ", "on the word ", "on okay?"] 

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

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

如果您使用带有组的模式,它也将返回结果中的模式:

 irb(main):007:0> "split it here and here okay".split(/ (here) /) => ["split it", "here", "and", "here", "okay"] 

编辑附加信息表明目标是使用拆分项目的一半包括拆分项目。 我认为有一个简单的方法可以做到这一点,但我不知道它,今天没时间玩它。 因此,在没有聪明的解决方案的情况下,以下是暴力破解的一种方法。 使用上述split方法在数组中包含拆分项。 然后遍历数组并将每个第二个条目(根据定义,它是拆分值)与前一个条目组合在一起。

 s = "split on the word on and include on with previous" a = s.split(/(on)/) # iterate through and combine adjacent items together and store # results in a second array b = [] a.each_index{ |i| b << a[i] if i.even? b[b.length - 1] += a[i] if i.odd? } print b 

结果如下:

 ["split on", " the word on", " and include on", " with previous"]