nfpyfzyf
nfpyfzyf

Reputation: 2991

How to do string increment in Javascript(Node.js)?

In ruby,

"a".next [or] "a".succ # => "b"
"aa".next # => "ab"
"z".next # => "aa" # two a's after one z

How to it in Javascript? Something like:

incr_str("aaa") ===> aab
incr_str("zzz") ===> aaaa

Upvotes: 3

Views: 1320

Answers (4)

serenesky0914
serenesky0914

Reputation: 59

Write a JavaScript function to get the successor of a string.

Note: The successor is calculated by incrementing characters starting from the rightmost alphanumeric (or the rightmost character if there are no alphanumerics) in the string. Incrementing a digit always results in another digit, and incrementing a letter results in another letter of the same case. If the increment generates a carry, the character to the left of it is incremented. This process repeats until there is no carry, adding an additional character if necessary.

console.log(successor("abcd"));     // "abce"
console.log(successor("THX1138"));  // "THX1139"
console.log(successor("<>"));       // "<>"
console.log(successor("1999zzz"));  // "2000aaa"
console.log(successor("ZZZ9999"));  // "AAAA0000"

function successor(str) {
  if (str.charAt(str.length - 1).match(/[a-z]|[0-9]/i) === null)
    // if not digit or letter
    return str;
  var lastCharCode = str.charCodeAt(str.length - 1) + 1; // increment last character

  if (lastCharCode == 123 || lastCharCode == 91 || lastCharCode == 58) {
    var newStr = str.slice(0, str.length - 1);
    lastCharCode == 58 ? (lastCharCode -= 10) : (lastCharCode -= 26); // go back 26 if its Z or z, 10 if 0
    var lastChar = String.fromCharCode(lastCharCode);

    return newStr.length > 0
      ? successor(newStr) + lastChar
      : (lastChar == "0" ? "1" + lastChar : lastChar + lastChar);
  }
  // in case of first number is 9 : add 1 in first position
  return str.slice(0, str.length - 1) + String.fromCharCode(lastCharCode);
}

Upvotes: 1

Andreas Hultgren
Andreas Hultgren

Reputation: 14953

A combination of String.fromCharCode() and "".charCodeAt() should be rather straight-forward to implement.

var FIRST = 97,
    LAST = 122;

function next (string) {
  var lastChar = string[string.length - 1];

  string = string.substring(0, string.length - 1);

  if(lastChar.charCodeAt(0) >= LAST) {
    // make last char a and append a
    lastChar = String.fromCharCode(FIRST) + String.fromCharCode(FIRST);
  }
  else {
    // Increase last char
    lastChar = String.fromCharCode(lastChar.charCodeAt(0) + 1);
  }

  return string + lastChar;
}

Very quick-and-dirty and behaves a bit weird (zzz -> zzaa instead of zaaa or zzza, not sure what behavior is best) , but it shows how you could go about implementing it (and atm i don't have time to write a more refined answer).

Upvotes: 0

Status BreakPoint
Status BreakPoint

Reputation: 114

I found RubyJs library. Please check it.

http://rubyjs.org/

<script src="ruby.min.js"></script>
<script>
var str = R("aaa");
alert(str.next());
</script>

Upvotes: 1

Stobor
Stobor

Reputation: 45132

A google search for "Ruby string succ Javascript" returns this gist from Devon Govett called "An implementation of Ruby's string.succ method in JavaScript" which appears to be what you're after...

/*
 * An implementation of Ruby's string.succ method.
 * By Devon Govett
 *
 * Returns the successor to str. The successor is calculated by incrementing characters starting 
 * from the rightmost alphanumeric (or the rightmost character if there are no alphanumerics) in the
 * string. Incrementing a digit always results in another digit, and incrementing a letter results in
 * another letter of the same case.
 *
 * If the increment generates a carry, the character to the left of it is incremented. This 
 * process repeats until there is no carry, adding an additional character if necessary.
 *
 * succ("abcd")      == "abce"
 * succ("THX1138")   == "THX1139"
 * succ("<<koala>>") == "<<koalb>>"
 * succ("1999zzz")   == "2000aaa"
 * succ("ZZZ9999")   == "AAAA0000"
 */

function succ(input) {
  var alphabet = 'abcdefghijklmnopqrstuvwxyz',
    length = alphabet.length,
    result = input,
    i = input.length;

  while(i >= 0) {
    var last = input.charAt(--i),
        next = '',
        carry = false;

    if (isNaN(last)) {
        index = alphabet.indexOf(last.toLowerCase());

        if (index === -1) {
            next = last;
            carry = true;
        }
        else {
            var isUpperCase = last === last.toUpperCase();
            next = alphabet.charAt((index + 1) % length);
            if (isUpperCase) {
                next = next.toUpperCase();
            }

            carry = index + 1 >= length;
            if (carry && i === 0) {
                var added = isUpperCase ? 'A' : 'a';
                result = added + next + result.slice(1);
                break;
            }
        }
    }
    else {
        next = +last + 1;
        if(next > 9) {
            next = 0;
            carry = true
        }

        if (carry && i === 0) {
            result = '1' + next + result.slice(1);
            break;
        }
    }

    result = result.slice(0, i) + next + result.slice(i + 1);
    if (!carry) {
        break;
    }
  }
  return result;
}

Upvotes: 4

Related Questions