Rub*_*uby 0 ruby string substring
我现在正在写一个Ruby宝石,但是我试图想到一个有效的方法在下面做到以下几点:
P<GBRLAST<<FIRST<MIDDLE<<<<<<<<<<<<<<<<<<<<<
Run Code Online (Sandbox Code Playgroud)
从那我想得到:GBR,最后,第一中间作为输出
我知道我可以使用类似的东西:
string[2...5]
Run Code Online (Sandbox Code Playgroud)
输出"GBR",但我如何将"最后"和"第一中间"作为其他输出?
总是<<在LAST和FIRST <之间,以及FIRST和MIDDLE之间,但LAST,FIRST和MIDDLE可以是任意长度(它们是示例名称),并且可能不仅仅是FIRST和MIDDLE与<分隔符.例如:
P<GBRLAST<<FIRST<MIDDLE<LION<<<<<<<<<<<<<<<<
Run Code Online (Sandbox Code Playgroud)
我能看到这样做的唯一方法是通过渐进式if循环,但有没有一种更有效和本地的方式将其拆分,我没有看到?
a = "P<GBRLAST<<FIRST<MIDDLE<LION<<<<<<<<<<<<<<<<"
parts = a.gsub(/<+/, '<').split('<')
# => ["P", "GBRLAST", "FIRST", "MIDDLE", "LION"]
Run Code Online (Sandbox Code Playgroud)
这会将所有'<<<<'字符串折叠为单个'<'字符,然后使用它作为分隔符将字符串拆分.
first = parts[1][0..2]
# => "GBR"
second = parts[1][3..-1]
# => "LAST"
the_rest = parts[2..-1]
# => ["FIRST", "MIDDLE", "LION"]
Run Code Online (Sandbox Code Playgroud)
做你想做的事.
这假定'first'总是3个字符长,但除非你有更多规则,否则我看不到任何其他分裂方式.
编辑:
评论者提出了一些很好的优化建议.
@ 7stud建议:
parts = a.gsub(/<+/, '<').split('<')
Run Code Online (Sandbox Code Playgroud)
可以改写为:
parts = a.split(/<+/)
Run Code Online (Sandbox Code Playgroud)
就处理器周期而言,这也更有效.
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>
Run Code Online (Sandbox Code Playgroud)
@Shadwell指出:
我们可以拆分单个'<'并删除空白条目以避免使用正则表达式.
a.split("<").select { |s| !s.empty? }
Run Code Online (Sandbox Code Playgroud)
避免正则表达式是一个很好的目标 - 正则表达式通常效率低下,是一种应用于字符串操作的通用语言,而不是优化的,有针对性的操作.它们也是不透明的,容易出错,容易出现边缘情况并且难以维护.
然而,在这种情况下,使用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>
Run Code Online (Sandbox Code Playgroud)
这里应该注意的是,除非我们处理真正大量的数据,否则不会真正感受到这些速度差异,因此应首先考虑代码可读性.
@careyswoveland评论我最喜欢的:
[a[2..4]].concat(a[5..-1].split(/<+/))
Run Code Online (Sandbox Code Playgroud)
它返回一个很好的所有值数组,并处理任意数量的额外字符串.需要进行一些精神上的解包才能理解正在发生的事情,但这是Ruby的强大和简洁的一个真正美丽的例子.
| 归档时间: |
|
| 查看次数: |
186 次 |
| 最近记录: |