Ruby:在边界上拆分字符串

时间:2015-01-30 13:51:02

标签: ruby regex

我有一串任意字符,其中一些是数字。我想将字符串分成由数字和非数字组成的字段。例如,如果我的字符串的值为'abc34d-f9',我想得到一个数组

['abc','34','d-f','9']

我几乎在那里,使用了后视和前瞻表达式:

s.split(/( (?<=\D)(?=\d) | (?<=\d)(?=\D) )/x)

这在边界数字 - >非数字之间的转换上分裂,反之亦然。但是,我也得到空元素,即这将返回

['abc','','34','','d-f','','9']

当然,从数组中过滤掉nullstrings是微不足道的。我只是想知道:为什么我会得到它们,我怎样才能做得更好?

2 个答案:

答案 0 :(得分:10)

使用string.scan函数返回匹配字符串数组。

> 'abc34d-f9'.scan(/\D+|\d+/)
=> ["abc", "34", "d-f", "9"]

\D+匹配\d+与一个或多个数字字符匹配的一个或多个非数字字符。

如果删除捕获组,您的正则表达式也可以正常工作。因为捕获组还会将分隔符(输入字符串被拆分的边界)返回到最终输出。

> 'abc34d-f9'.split(/(?<=\D)(?=\d)|(?<=\d)(?=\D)/)
=> ["abc", "34", "d-f", "9"]
> 'abc34d-f9'.split(/ (?<=\D)(?=\d) | (?<=\d)(?=\D) /x)
=> ["abc", "34", "d-f", "9"]

答案 1 :(得分:1)

虽然我更喜欢@ AvinashRaj的解决方案,但尝试寻找其他方法总是很有趣(而且有时通常具有指导意义):

str = 'abc34d-f9'

a = str.split(/(\d+)/)    #=> ["abc", "34", "d-f", "9"] 
a.shift if a.first.empty? #=> nil
a                         #=> ["abc", "34", "d-f", "9"] 

a = str.split(/(\D+)/)    #=> ["", "abc", "34", "d-f", "9"] 
a.shift if a.first.empty? #=> "" 
a                         #=> ["abc", "34", "d-f", "9"] 

str.each_char.chunk { |c| !!(c =~ /\d/) }.map { |_,a| a.join }
                          #=> ["abc", "34", "d-f", "9"] 

str[1..-1].each_char.with_object([str[0]]) { |c,a|
  ((c + a.last[0]) =~ /\d{2}|\D{2}/) ? a.last << c : a << c }
                          #=> ["abc", "34", "d-f", "9"] 

(Ruby 2.2)
str.each_char.slice_when { |a,b| (a+b) =~ /\d\D|\D\d/ }.map(&:join)
                          #=> ["abc", "34", "d-f", "9"]