Dennis
Dennis

Reputation: 1975

How to increase latest number inside string and parenthesis in Ruby (Rails)

I have a string like this:

Hello (0)

also can have this too:

Hello 12345 (0) (1) (65)

What im trying to do is increase last number. In this case expected result will be like this:

Hello (1)
Hello 12345 (0) (1) (66)

Is there any way to do this magically in Ruby or regex? How can i keep all numbers in all parenthesis but increase the last one?

Note that, string can have unicode letters in it so the result should not be broken.

Upvotes: 0

Views: 125

Answers (4)

asimhashmi
asimhashmi

Reputation: 4378

You can use this regex to achieve what you want

\((\d+)\)(?!.*\(\d+\))

In ruby you can use the following code to change your string

"Hello 12345 (0) (1) (66)".str.sub(/\((\d+)\)(?!.*\(\d+\))/) { |s| s.succ }

// => Hello 12345 (0) (1) (67)

Upvotes: 1

Cary Swoveland
Cary Swoveland

Reputation: 110755

str = "Hello 12345 (0) (1) (65) (33a)"

str.sub(/.*\(\d+\)/, &:succ)
  #=> "Hello 12345 (0) (1) (66) (33a)"

.* is greedy so it gobbles up all characters, including '(0)' and '(1)', until it gets to the last match of \(\d+\).

Upvotes: 2

Yule
Yule

Reputation: 9774

Regex can scan for teh different parts:

> s = "Hello 12345 (0) (1) (65)"
> value = s.scan(/((.*)\((\d+)\)\z)/).first

This will match any string, followed by a '(', followed by any number of digits, followed by ')' then the end of the string. You then have an array, which you can manipulate. The (unescaped) parenthesis in the pattern above groups the inputs:

value is ["Hello 12345 (0) (1) (65)", "Hello 12345 (0) (1) ", "65"]

It's then a case of putting them together

"#{value[1]}(#{value[2].to_i + 1})"

Obviously this doesn't deal with error cases etc but gives you a start

Upvotes: 1

Marlin Pierce
Marlin Pierce

Reputation: 10099

First find the last parenthesised part

/\(.*\)[^\(\)]*\z/

This finds a pair of parentheses with something inside it, followed by any non-parentheses until the end of the string.

Next, bind that to a variable.

/\((?<lastnum>.*)\)[^\(\)]*\z/ =~ input_string

Finally build the output string.

if /\A(?<prior>.*)\((?<lastnum>.*)\)[^\(\)]*\z/ =~ input_string
    "#{prior}(#{lastnum + 1})"
end

Upvotes: 1

Related Questions