a = "P<GBRLAST<<FIRST<MIDDLE<LION<<<<<<<<<<<<<<<<"
parts = a.gsub(/<+/, '<').split('<')
# => ["P", "GBRLAST", "FIRST", "MIDDLE", "LION"]
这会将所有 '
first = parts[1][0..2]
# => "GBR"
second = parts[1][3..-1]
# => "LAST"
the_rest = parts[2..-1]
# => ["FIRST", "MIDDLE", "LION"]
随心所欲。
这假定“第一”总是 3 个字符长,但我看不到任何其他拆分方式,除非您有更多规则。
编辑:
评论者建议的一些出色的优化。
@7stud 建议:
parts = a.gsub(/<+/, '<').split('<')
可以改写为:
parts = a.split(/<+/)
这在处理器周期方面也更有效。
Benchmark.measure { 10000.times { a.split(/<+/) }}
# => #<Benchmark::Tms:0x007fc0320b84a8 @label="", @real=0.053515, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.04999999999999999, @total=0.04999999999999999>
Benchmark.measure { 10000.times { a.gsub(/<+/, '<').split('<') }}
# => #<Benchmark::Tms:0x007fc0328fe3d8 @label="", @real=0.081377, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.07999999999999996, @total=0.07999999999999996>
@Shadwell 指出:
我们可以只拆分一个“
a.split("<").select { |s| !s.empty? }
避免正则表达式是一个很好的目标 - 正则表达式通常效率低下,它是一种适用于字符串操作的通用语言,而不是一种优化的、有针对性的操作。它们也不透明、容易出错、容易出现极端情况且难以维护。
然而,在这种情况下,使用 select 比在正则表达式上拆分效率要低一些。此外,正则表达式很简单,不用担心太多。
Benchmark.measure { 10000.times { a.split(/<+/) }}
# => #<Benchmark::Tms:0x007fc0320b84a8 @label="", @real=0.053515, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.04999999999999999, @total=0.04999999999999999>
Benchmark.measure { 10000.times { a.split("<").select { |s| !s.empty? } }}
# => #<Benchmark::Tms:0x007fc032039ea0 @label="", @real=0.061219, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.06, @total=0.06>
这里应该注意的是,除非我们处理真正大量的数据,否则不会真正感受到这些速度差异,因此代码可读性应该是第一位的。
@careyswoveland 评论了我最喜欢的:
[a[2..4]].concat(a[5..-1].split(/<+/))
它返回一个包含所有值的漂亮数组并处理任意数量的额外字符串。需要一点精神上的解包来理解发生了什么,但它是 Ruby 的强大和简洁的一个真正美丽的例子。