How to identify a string as a binaryoperator - python

Perhaps this is an easy question, but I'm new to Python and haven't seen anyone else post anything similar to this.
We have a list:
lst1 = ["5", "+", "1"]
or
lst2 = ["10", "/", "2"]
How can one interpret this to: 5 + 1 or 10/2 ? I understand that you can write: int(lst2[0]) and then you would get 10, but how do you do the same with "+" or "/"?

Assuming you "know" that your list has three strings, with the first and last representing integers and the middle one representing one of a fixed set of operators, you just need a mapping from the operator to a function that implements it. For example:
import operator
ops = {"+": operator.add, "-": operator.sub, "*": operator.mul, "/": operator.div}
lst1 = ["5", "+", "1"]
f = ops[lst1[1]]
operand1 = int(lst1[0])
operand2 = int(lst1[2])
result = f(operand1, operand2)
However, things get complicated once you start allowing more general inputs, as you need some logic for deciding what parts of the list represent what. For that, you need:
A grammar, which identifies what role each element of your list plays
A parser, which uses the grammar to convert each string to a usuable value
An interpreter, which evaluates the thing produced by the parser to produce
a final value.
There may also be a tokenizer, which is what would convert a single string input like "5 + 1" into a list of tokens that the parser uses for its input.
Any further general discussion about how to define any of the 4 concepts defined above is far beyond the scope of Stack Overflow.

If I understand you right, here is a snippet you may start with:
import operator
operators = {'+': operator.add, '-': operator.sub, '/': operator.truediv, '*': operator.mul}
first, op, second = lst
first, op, second = int(first), operators[op], int(second)
op(first, second)
operator module contains operators as a functions, so you can map symbols to the operators. Note that I’ve used truediv for /, you may want to use variant which return int always

You can't transform the string "+" to the operator + because operators are not things that exist at runtime. Operators only exist in code. You can map the string "+" to a function that takes two arguments and returns their sum, though. Functional equivalents for most operators exist in the operator module:
lst1 = ["5", "+", "1"]
import operator
op_table = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv
}
lhs = int(lst1[0])
op = op_table[lst1[1]]
rhs = int(lst1[2])
print('result:', op(lhs, rhs)) # output: 6

You can use standard function eval()
https://www.journaldev.com/22504/python-eval-function
lst1 = ["5", "+", "1"]
result1 = eval("".join(lst1)) # 6
lst2 = ["10", "/", "2"]
result2 = eval("".join(lst2)) # 5.0

Related

How to solve expressions from a list?

I have a list of expressions (+ - *):
["2 + 3", "5 - 1", "3 * 4", ...]
and I need to convert every expresion to expression = answer like this 2 + 3 = 5.
I tried just doing print(listt[0]) but it outputs 2 + 3, not 5. So how do i get the answer of this expression? I know that there is a long way by doing .split() with every expression, but is there any other faster way of doing this?
UPD: I need to use only built-in functions
You can use the eval() function from Python Builtins :
for expr in yourlist:
print(expr, "=", eval(expr))
# 2+3 = 5
As stated in the comments, this is not malicious-proof. Use this only if you know the string being evaluated are indeed simple arithmetic expressions.
If you want to avoid using eval() (and you probably should) then you could do something like this:
from operator import add, sub, mul, truediv
from re import compile
OMAP = {
'+': add,
'-': sub,
'*': mul,
'/': truediv
}
pattern = compile(r'^(\d+\.*\d*)\s*(.)\s*(\d+\.*\d*)$')
exprs = ["2 + 3.5", "5 - 1", "3 * 4", "3 / 4"]
def convert(s):
try:
return int(s)
except ValueError:
pass
return float(s)
for expr in exprs:
x, o, y = pattern.findall(expr)[0]
r = OMAP[o](convert(x), convert(y))
print(f'{expr} = {r}')
Output:
2 + 3.5 = 5.5
5 - 1 = 4
3 * 4 = 12
3 / 4 = 0.75
Note:
This is not robust as it assumes that the operators are only ever going to be one of +, -, *, / and furthermore that the pattern always matches the regular expression.
Input data changed to include a floating point number
Use eval() function. The eval() function evaluates the specified expression, if the expression is a legal Python statement, it will be executed.

How to use some operator that has been scraped from a string

I'm trying to add, subtract or multiply two integers based on the sign between the integers, as in 5 + 6. When I use + explicitly within the script, it works. However, I wish to parse that operator from the given string in order to use like int(numbers[0]) + operator + int(numbers[1]) or something similar that works.
I've tried with:
import re
str_number = "5 + 6"
numbers = re.findall('[0-9]+', str_number)
operator = re.findall('([^\s\d]+?)',str_number)[0]
result = int(numbers[0]) + operator + int(numbers[1])
print(result)
When I run the above, I get the error below:
result = int(numbers[0]) + operator + int(numbers[1])
TypeError: unsupported operand type(s) for +: 'int' and 'str'
You can use the inbuilt operator module and define a mappings dictionary that map the given operator to its corresponding operation.
Use:
import operator
mappings = {'+': operator.add, '-': operator.sub, '*': operator.mul, '/': operator.floordiv}
equation = "5 + 6"
n1, op, n2 = equation.split()
result = mappings[op](int(n1), int(n2))
print(result)
This prints:
11
If I am correct it is not possible because the operator variable is a str but the number number variable is an int and you can’t do anything with these without type conversion
But you could accomplish your idea by using an if else statement.
try it that works, transform you equation in a string and use the eval() function
result = numbers[0] + operator + numbers[1]
print(eval(result))

Python Performing Calculations with Strings

How do I perform calculations with strings? Like suppose I have:
a=('/')
print(10, a, 5)
How do I get the answer as '2'? Because 10/5 is 2.
There are multiple ways to do this.
The most common way, I guess, is using the operator module and a map (dictionary) to turn your strings into operators, as the next example.
import operator
run_ops = {
'+' : operator.add,
'-' : operator.sub,
'*' : operator.mul,
'/' : operator.truediv,
'%' : operator.mod,
'^' : operator.xor,
}.get
print(run_ops('/')(10, 5))
Or go with lambdas:
run_ops= {'+': lambda x, y: x + y,
'-': lambda x, y: x - y,
# ...
'/': lambda x, y: x / y
}
run_ops['/'] (10,5)
Cheers
A nice method has been posted by epap.
However if you want to stick to the order of the expression where the "/", comes between the two numbers then one of the ways you can do it, is as below.
You can wrap (Number_1, "/", Number_2) and send it to a class and then print it. Something like below.
class Divide(object):
def __new__(cls, a, symbol, b):
result = None
if symbol == "/":
result = a/b
return result
print(Divide(5,"/",2))
This yields the below output
2.5
You can use "eval" to evaluate expressions given as strings.
a = "/"
res = eval("10" + a + "5")
print(res)

How do I put mathematical operations in a list?

I need to make my code as short as possible and I need to put * - + in a list like this: op = [*,-,+]
It gives me a syntax error... I know I can put them as strings but is that the only way? My program picks a random operator from that list and makes a sum out of it, eg, sum = num1 op num2
my code:
import random
opL = [*,-,+]
def mathsQuiz(number1,operator,number2):
sum1=number1,operator,number2
print(sum1)
number1 = random.randint(1,12)
number2 = random.randint(1,12)
operator = random.choice(opL)
mathsQuiz(number1,operator,number2)
Use the operator module and create a dictionary instead that will map out your operators:
>>> import operator
>>> import random
>>> opL = {"*": operator.mul, "-": operator.sub, "+": operator.add}
>>> opL.get(random.choice(list(opL)))(1,2)
3
import operator
opL = operator.mul, operator.sub, operator.add

Evaluation of Postfix notation

How to calculate the value of post fix notation:
i tried with:
import operator
operator = {
'+': operator.add, '-': operator.sub,
'*': operator.mul, '/': operator.div, '%': operator.mod,
'**': operator.pow, '//': operator.floordiv,
}
l = []
exp = "11+2*"
for i in exp:
if i in operator:
a = operator[i]
x = l[0]
y = l[1]
l[-2:] = [a(*l[-2:])]
print l
else:
l.append(i)
print l
How to do this?
Make sure to have Python parse your characters into integers before adding them to the stack:
l.append(int(i))
Some hints:
You need a better parser, iterating just character by character will not be enough (unless you only want to have single digit numbers). To make it a little simpler, you could require that numbers and operators are delimited by whitespace each and use str.split:
elems = "11 2 3 + *".split()
You need to convert the numbers to integers before pushing them on the stack
The stack operation also looks a little weird. Having it as
l.append(a(l.pop(), l.pop())
makes it more explicit.

Categories

Resources