1

I have a string that has numbers and math operators (+,x,-, /) mixed in it

'12+345x6/789'

I need to convert it into an array seperated by those math operators.

[12, +, 345, x, 6, /, 789]

What is a simple way of doing this?

6
  • I looked into regex and String.prototype.split but I can't find a way to implement this easily in a 1 or 2 liner Commented Mar 29, 2018 at 1:00
  • How do you want to handle what is neither an operator nor a digit? My approach strips them. Commented Mar 29, 2018 at 1:12
  • @AluanHaddad hm I didn't think about that. The other solutions are either all digits or all nondigits....... but yours is all digits, operators, and everything else? Commented Mar 29, 2018 at 1:18
  • No my solution discards anything that is not a digit or an op Commented Mar 29, 2018 at 1:20
  • 1
    Yes, that's what it does except for whitespace between numbers, which it retains, keeping them together Commented Mar 29, 2018 at 1:23

3 Answers 3

2

Splitting on consecutive non-digit chars \D+ you get

console.log ('12+345x6/789'.split (/\D+/))
// [ '12', '345', '6', '789' ]

If you add a capture group, (\D+) you get the separator too

console.log ('12+345x6/789'.split (/(\D+)/))
// [ "12", "+", "345", "x", "6", "/", "789" ]

If you want to support parsing decimals, change the regexp to /([^0-9.]+)/ - Note, \D used above is equivalent to [^0-9], so all we're doing here is adding . to the character class

console.log ('12+3.4x5'.split (/([^0-9.]+)/))
// [ "12", "+", "3.4", "x", "5" ]

And a possible way to write the rest of your program

const cont = x =>
  k => k (x)

const infix = f => x =>
  cont (f (x))

const apply = x => f =>
  cont (f (x))

const identity = x =>
  x

const empty =
  Symbol ()
  
const evaluate = ([ token = empty, ...rest], then = cont (identity)) => {
  if (token === empty) {
    return then
  }
  else {
    switch (token) {
      case "+":
        return evaluate (rest, then (infix (x => y => x + y)))
      case "x":
        return evaluate (rest, then (infix (x => y => x * y)))
      case "/":
        return evaluate (rest, then (infix (x => y => x / y >> 0)))
      default:
        return evaluate (rest, then (apply (Number (token))))
    }
  }
}

const parse = program =>
  program.split (/(\D+)/)
  
const exec = program =>
  evaluate (parse (program)) (console.log)

exec ('')             // 0
exec ('1')            // 1
exec ('1+2')          // 3
exec ('1+2+3')        // 6
exec ('1+2+3x4')      // 24
exec ('1+2+3x4/2')    // 12
exec ('12+345x6/789') // 2

Sign up to request clarification or add additional context in comments.

4 Comments

2nd solution doesn't have seperators in it can you double check
where exactly is the capture group on 2nd solution (aren't they normally $1,$2, etc)? Having trouble understanding this one
Okay I found its on MDN page developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…. "If separator is a regular expression that contains capturing parentheses, then each time separator is matched, the results (including any undefined results) of the capturing parentheses are spliced into the output array. However, not all browsers support this capability."
By the way I noticed something wrong with this solution. If you used 12+345x as the input the output becomes[12,+,345,""]
2

If you are unconcerned with whitespace, all you need is

'12+345x6/78-9'.match(/\d+|[\+-\/x]/g);

which splits the string into numbers and the +, -, \, and x tokens.

'use strict';
const tokens = '12+345x6/78-9'.match(/\d+|[\+-\/x]/g);

console.log(tokens);

To handle whitespace, consider

'12+3 45 x6/78-9'.match(/\d|\d[\s\d]\d|[\+-\/x]/g);

which splits the string into numbers (optionally allowing whitespace as a digit separator within a single number) and +, -, \, and x.

'use strict';
const tokens = '12+3 45 x6/78-9'.match(/\d+\s?\d+|\d+|[\+-\/x]/g);


console.log(tokens);

3 Comments

You forgot the x
could you put the original simple version you had too ? :)
@Kagerjay found a bug and fixed it.
1

this is going to work

console.log('12+345x6/789'.match(/\D+|\d+/g))

2 Comments

is this seperating by digits \d+ and nondigits \D+
@Kagerjay,yes,you got it

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.