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)
小智 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)