我有一串任意字符,其中一些是数字。我想将字符串分成由数字和非数字组成的字段。例如,如果我的字符串的值为'abc34d-f9',我想得到一个数组
['abc','34','d-f','9']
我几乎在那里,使用了后视和前瞻表达式:
s.split(/( (?<=\D)(?=\d) | (?<=\d)(?=\D) )/x)
这在边界数字 - >非数字之间的转换上分裂,反之亦然。但是,我也得到空元素,即这将返回
['abc','','34','','d-f','','9']
当然,从数组中过滤掉nullstrings是微不足道的。我只是想知道:为什么我会得到它们,我怎样才能做得更好?
答案 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"]