1
\$\begingroup\$

This parses two digits and returns the rest of the string.

Input:

"20asg"

Output:

{ number: 20, left: "asg" }

Input:

"9asg"

Output:

{ number: 9, left: "asg" }

function readDigit(str) {
  var digitMap = {
    0: 0,
    1: 1,
    2: 2,
    3: 3,
    4: 4,
    5: 5,
    6: 6,
    7: 7,
    8: 8,
    9: 9
  };

  var number1 = digitMap[str[0]];
  var number2 = digitMap[str[1]];

  if (number2 === undefined) {
    if (number1 === undefined) {
      return {
        left: str.slice(1)
      };
    }
    return {
      number: number1,
      left: str.slice(1)
    };
  } else {
    return {
      number: (number1 * 10) + number2,
      left: str.slice(2)
    };
  }
}
\$\endgroup\$

2 Answers 2

6
\$\begingroup\$

This seems like a perfect job for a simple regular expression:

/^(\d+)(.*)$/

That pattern matches a string starting with (^) one or more digits (\d+), and whatever comes after it (.*). The parentheses make the two parts into explicit capture groups.

So you can do this

function readDigit(str) {
  var match = str.match(/^(\d+)(.*)$/);

  if(!match) {
    return { left: str };
  }

  return {
    number: parseInt(match[1], 10),
    left: match[2]
  };
}

Edit: If you specifically want to find 2 digits (not just 1-or-more), you can use the following pattern instead:

/^(\d\d)(.*)$/

or its equivalent:

/^(\d{2})(.*)$/
\$\endgroup\$
3
  • \$\begingroup\$ This is almost certainly a non-issue but your answer will output 9 for 09ahshd \$\endgroup\$
    – Daniel F
    Commented Mar 20, 2016 at 2:21
  • \$\begingroup\$ @DanielF So will OP's code. While it doesn't use parseInt (though it should), it still maps stringified digits to their numeric values. And the string "09" thus becomes the number 9. \$\endgroup\$
    – Flambino
    Commented Mar 20, 2016 at 2:34
  • \$\begingroup\$ Thanks. I missed the (number1 * 10) + number2 and thought they were concating them \$\endgroup\$
    – Daniel F
    Commented Mar 20, 2016 at 4:16
3
\$\begingroup\$

Instead of looking at the first two characters separately, you can just slice off digits from the beginning of the string until you reach the desired length. That also allows you to check if there are any more characters in the source strings, so that it can handle strings like "a", "1" or even an empty string without crashing.

I assume that the expected result when no digits are found should be the entire string, not the string with the first character sliced off as in the original code. I.e. when input is "asg" the output would be { left: "asg" } rather than { left: "sg" }.

Accessing strings using brackets works in all modern browsers, but you might want to use the charAt method instead which works on all platforms.

function readDigit(str) {
  var n = 0;
  while (n < 2 && n < str.length && str.charAt(n) >= '0' && str.charAt(n) <= '9') {
    n++;
  }
  var result = { left: str.substr(n) };
  if (n.length) result.number = parseInt(str.substr(0, n), 10);
  return result;
}

You can make the function more flexible (reusable) by adding a maxLength parameter, and use n < maxLength instead of n < 2.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.