I have an array which contains elements that are boolean values (True
, False
) and strings which represent logical operators ('and'
, 'or'
, 'not'
).
For example:
array = [True, 'and', False]
I'd like to take the elements of this array in order and turn them into an actual expression I can assign a variable to. Meaning the following:
expression = True and False
So that I can then print the boolean result of said expression
print("The result of the expression is = ", expression)
Which should return
The result of the expression is = False
How could I achieve this? My vague idea is to iterate through the array, but I'm having a hard time figuring out how to turn a string ('and'
) to an operator (and
).
TIA.
CodePudding user response:
Here is a simple 3-step iterative algorithm to solve this without relying on eval
, and assuming and
has higher operator precedence than or
. If there is no operator precedence, you could combine steps 2 and 3 into a single iteration.
- First, iterate through the array, getting rid of all
not
. For instance, convert allnot True
toFalse
and vice versa. Now we are left with onlyand
,True
,or
, andFalse
. - Then, iterate through the array evaluating all
and
expressions. - Finally, return
True
if there are anyTrue
left in the array, otherwise returnFalse
.
Here's an implementation. It's not the most efficient, since deleting in the middle of a list takes O(n), but it shows how the algorithm works:
from copy import copy
def remove_nots(lst):
i = 0
while i < len(lst):
# if we encounter a `not`, remove it, and negate the following element
if lst[i] == 'not':
del lst[i]
# to negate a `not`, we remove it
if lst[i] == 'not':
del lst[i]
# otherwise, it must be a boolean, so we can use native not
else:
lst[i] = not lst[i]
else:
i = 1
def resolve_and(lst):
i = 0
while i 2 < len(lst):
# if we encounter an `and` expression, replace it with the result
if lst[i 1] == 'and':
result = lst[i] and lst[i 2]
del lst[i 2]
del lst[i 1]
lst[i] = result
else:
i = 1
def resolve(lst):
# create a copy to work on, since we'll be modifying the list
lst_copy = copy(lst)
remove_nots(lst_copy)
resolve_and(lst_copy)
return True in lst_copy
print(resolve(lst = [False, 'or', True, 'and', 'not', 'not', 'not', False])) # True
CodePudding user response:
This should work:
array = [True, 'and', False]
expression = eval(' '.join([str(i) for i in array]))
print("The result of the expression is = ", expression)
Output:
The result of the expression is = False