
First of all, it's okay to be a beginner - I was in your exact shoes just a few years ago!
I'm going to attempt to provide an elementary/beginner approach to solving this problem, with just the basics.
So first we want to determine what the limits of our function input will be. For this, I'll assume we only accept mathematical expressions with basic addition/subtraction operators.
import re
def calculate(expression: str) -> int:
if not re.match("^[0-9\+-]*$", expression):
return None
For this you'll see I opted for regex, which is a slightly more advanced concept, but think about it like a validity check for expression
. Basically, the pattern I wrote checks that there is a fully qualified string that has only integers, plus sign, and minus sign. If you want to learn more about the expression ^[0-9\+-]*$
, I highly recommend https://regexr.com/.
For our purposes and understanding though, these test cases should suffice:
>>> re.match("^[0-9\+-]*$", "abcs")
>>> re.match("^[0-9\+-]*$", "1+2")
<re.Match object; span=(0, 3), match='1+2'>
>>> re.match("^[0-9\+-]*$", "1+2/3")
>>>
Now that we have verified our expression, we can get to work on calculating the final value.
Let's try your idea with str.split()
! It won't be entirely straightforward because split
by definition splits a string up according to a delimiter(s) but discards them in the output. Fear not, because there's another way! The re
package I imported earlier can come into handy. So the re
library comes with a handy function, split
!
By using capture groups for our separator, we are able to split and keep our separators.
>>> re.split("(\d+)", "1+393958-3")
['', '1', '+', '393958', '-', '3', '']
So, with this up our sleeve...
import re
def calculate(expression: str) -> int:
if not re.match("^[0-9\+-]*$", expression):
return None
expression_arr = re.split("(\d+)", expression)[1:-1]
while len(expression_arr) > 1:
# TODO stuff
return int(expression[0])
We can now move onto our while loop. It stands to reason that as long as the array has more than one item, there is some sort of operation left to do.
import re
def calculate(expression: str) -> int:
if not re.match("^[0-9\+-]*$", expression):
return None
expression_arr = re.split("(\d+)", expression)[1:-1]
while len(expression_arr) > 1:
if expression_arr[1] == "+":
eval = int(expression_arr[0]) + int(expression_arr[2])
if expression_arr[1] == "-":
eval = int(expression_arr[0]) - int(expression_arr[2])
del expression_arr[:3]
expression_arr.insert(0, eval)
return int(expression_arr[0])
It's pretty straightforward from there - we check the next operator (which always has to be at expression_arr[1]
) and either add or subtract, and make the corresponding changes to expression_arr
.
We can verify that it passes the test case you provided. (I added some logging to help with visualization)
>>> calculate("5+8-3+9")
['5', '+', '8', '-', '3', '+', '9']
[13, '-', '3', '+', '9']
[10, '+', '9']
[19]
19