如何分割字符串,同时保存分割元素为空字符串?



我正在尝试拆分字符串,以便已"拆分"的元素;被保存为空字符串,例如,对于字符串"abaca",我需要结果是["", "b", "", "c", ""]或字符串"xzxzxz",结果是["x","","x","","x",""]简单地添加空元素是行不通的,因为我不知道我分裂的元素是否存在于字符串的开始或结束。

我试着使用穿插,但是我发现的每一种方法都导致了错误或不是我想要的。除此之外,我还没有找到其他有用的东西。

对于这个问题,匹配正则表达式比拆分正则表达式更方便。

def doit(str, spl)
sp = Regexp.escape(spl)
str.gsub(/#{sp}|.+?(?=#{sp}|$)/).map { |s| s == spl ? " " : s }
end

doit('abaca', 'a')             #=> [" ", "b", " ", "c", " "]
doit('xzxzxz', 'z')            #=> ["x", " ", "x", " ", "x", " "]  
doit('nowiswasistoday', 'is')  #=> ["now", " ", "was", " ", "today"]
doit('iswasistoday', 'is')     #=> [" ", "was", " ", "today"] 
doit('i?si?s', '?')            #=> ["i", " ", "si", " ", "s"]


下面是一个步骤示例。

str = 'iswasistoday'
spl = 'is'
sp = Regexp.escape(spl)
#=> "is"

这里我使用Regexp.escape来转义spl中在正则表达式中具有特殊意义的字符。在这种情况下,我们看到spspl相同,但是在上面的最后一个示例中,?在正则表达式中具有特殊的含义(即使匹配可选或匹配尽可能少的字符)。在这种情况下,Regexp.escape('?') #=> "\?"。在继续,

rgx = /#{sp}|.+?(?=#{sp}|$)/
#=> /is|.+?(?=is|$)/
enum = str.gsub(rgx)
#=> #<Enumerator: "iswasistoday":gsub(/is|.+?(?=is|$)/)>

这里我使用String#gsub的形式,它接受单个参数而没有块,返回一个枚举器,生成它的参数的匹配,这里是一个正则表达式。通过将该枚举数转换为数组,可以看到将生成的匹配项。

enum.to_a
#=> ["is", "was", "is", "today"]

最后一步在后面。

enum.map { |s| s == spl ? " " : s }
#=> [" ", "was", " ", "today"]

正则表达式包含以下元素:

/
#{sp}     match the value of the variable sp
|         or
.+        match one or more characters other than line terminators
?         make previous match relunctant, matching as few characters as possible
(?=       begin a positive lookahead
#{sp}   match the value of the variable sp
|       or
$       match the end of the string
)         end the positive lookahead
/

您可以使用each_char来迭代每个字符,然后自己映射它们。

'abaca'.each_char.map { |c| c.eql?('a') ? ' ' : c }
=> [" ", "b", " ", "c", " "]
'xzxzxz'.each_char.map { |c| c.eql?('z') ? ' ' : c }
=> ["x", " ", "x", " ", "x", " "]

最新更新