Removing multiple zeros from a string if only zeros are input

Viewed 96

I'm trying to implement a method that if the user inputs a series of zero like "00000" it should return "0"

Otherwise, if the user inputs for example "00009" or "90000", the input variable should remain unchanged.

Is there a simple solution for this problem?

4 Answers
def doit(str)
  str.squeeze == '0' ? '0' : str
end
doit("00000") #=> "0"
doit("00009") #=> "00009"
doit("90000") #=> "90000"

See the last sentence of the doc String#squeeze.

Try this

"0000000".gsub(/^0+$/, '0')
 => "0" 
"0000009".gsub(/^0+$/, '0')
 => "0000009" 
 => "0" 
"9000000".gsub(/^0+$/, '0')
 => "9000000" 

You can do it using regular expressions as follow:

def validate_sequence(sequence:)
   r = /\A(^0+[1-9]+\z)|(\A[1-9]+[0-9]+\z)/
   sequence.match?(r) ? sequence : '0'
end

The code above returns the same sequence if the sequence matches the regex or 0 in another case, the regex validates that a sequence is a valid number or if end with a valid sequence of numbers, the double ? change the result of the match function and returns a boolean value.

You can use the code above as follow: validate_sequence(sequence: '0000000')

If you want to only match digits distinct of 0 at the beginning and at the end you can do it by changing the value of r like this: r = /(^0+[1-9]+$)|(^[1-9]+0+$)/.

When the string always contains only digits then you might want to consider:

sequence.to_i.zero? ? '0' : sequence

IMHO it is always interesting to run a benchmark when there are so many different solutions

require 'benchmark/ips'

Benchmark.ips do |x|
  examples = %w[00000 00001 12345]

  def cary_swoveland(str)
    str.squeeze == '0' ? '0' : str
  end

  def r4cc00n(str)
     r = /(^0+[1-9]+$)|(^[1-9]+[0-9]+$)/
     !!str.match(r) ? str : '0'
  end

  def spickermann(str)
    str.to_i.zero? ? '0' : str
  end

  def ursus(str)
    str.gsub(/^0+$/, '0')
  end

  %w[cary_swoveland r4cc00n spickermann ursus].each do |algorithm|
    x.report(algorithm) { examples.each { |e| send(algorithm, e) } }
  end

  x.compare!
end

Result:

$ ruby benchmark.rb 
Warming up --------------------------------------
      cary_swoveland    86.149k i/100ms
             r4cc00n    24.258k i/100ms
         spickermann    94.211k i/100ms
               ursus    21.714k i/100ms
Calculating -------------------------------------
      cary_swoveland    833.459k (± 2.2%) i/s -      4.221M in   5.067333s
             r4cc00n    231.787k (± 6.9%) i/s -      1.164M in   5.050636s
         spickermann    905.658k (±10.0%) i/s -      4.522M in   5.097849s
               ursus    213.674k (± 2.3%) i/s -      1.086M in   5.083811s

Comparison:
         spickermann:   905658.0 i/s
      cary_swoveland:   833459.1 i/s - same-ish: difference falls within error
             r4cc00n:   231787.4 i/s - 3.91x  (± 0.00) slower
               ursus:   213674.2 i/s - 4.24x  (± 0.00) slower
Related