Reputation: 23
I am working on a jQuery calculator which has a live display which will look like this:
let liveDisplayString = $('#liveDisplay').val();
// ex. '42.5*30.6' or '7/2'
I am trying to separate out the numbers by the operators +
, -
, *
and /
and then assign the list items to variables for use in calculation. I also need to grab the operator so I would need another expression to ignore 1-9 and the decimal.
I'm really struggling to understand how to create a regular expression to use in .match()
.
P.S. I am still very new to programming and the JS language
Upvotes: 1
Views: 938
Reputation: 31992
You can use String#split
along with regex to get the job done.
The following extracts the operators +
, -
, *
and /
.
const value = '42.5*30.6+6-2/6';
const numbers = value.split(/[*]|[+]|[-]|[\/]/);
const operators = value.split(/[^-|+|\/|\*]/).filter(e => e);
console.log(numbers);
console.log(operators);
Upvotes: 2
Reputation: 8718
Parsing expressions can get quite complicated.
In your case, if an expression is always of the form <value> <operator> <value>
(with or without whitespace), you could split by operator:
const OPERATORS = {
'*': (a, b) => a * b,
'/': (a, b) => a * b,
'+': (a, b) => a * b,
'-': (a, b) => a * b,
};
function evaluate(input) {
// Loop over the keys, e.g. '*', '/', ...
for (const operator in OPERATORS) {
// Split e.g. '1 + 2' into ['1 ', ' 2']
// but if the operator is '*' and we have '1+2' we get ['1+2']
const split = input.split(operator);
if (split.length === 2) {
// ^ There was exactly one <operator> in the string
let [a, b] = split;
// Trim, e.g. "42.5 " into "42.5" then parse as a float
a = parseFloat(a.trim());
b = parseFloat(b.trim());
// Get the arrow function from OPERATORS and return the call result
return OPERATORS[operator](a, b);
}
}
throw new Error(`Invalid expression!`);
}
console.log(evaluate('42.5 * 30.6'));
If you're new to JS, this might already start to look a bit complicated, and this is just for <value> <operator> <value>
. If you actually want to start handling e.g. 5 + 2 * 3 + 3
, it's a lot more work.
You could simply parse left-to-right, e.g. [5, '+', 2, '*', 3, '+', 3]
, but remember the order of operations. You want to evaluate it as (5 + (2 * 3)) + 3
and not as ((5 + 2) * 3) + 3
. You'll need to use of an algorithm there to "swap" the binary operations properly. But perhaps that's a topic for much later.
To actually use RegEx for this, that's also an option:
const input = '42.5 * 30.6';
const match = input.match(/^\s*(\d*\.\d+)\s*(\*|\/|\+|\-)\s*(\d*\.\d+)$/);
// Array destructuring, e.g. [0,1,2,3] results in a=1, op=2, b=3
const [, a, op, b] = match;
console.log('a', a);
console.log('op', op);
console.log('b', b);
The RegEx uses \s*
everywhere to say "there can be whitespace here, but doesn't need to" while (\d*\.\d+)
allows (decimal) numbers, while (\*|\/|\+|\-)
wants a operator. We need to escape it with \
because these are all special characters in RegEx.
Upvotes: 1