[英]Easy way to check precedence of ( “and”, “or”) in python
I have a python list like this 我有一个像这样的python列表
[True, "and", False, "or", False, "or", True ....]
How to operate them and find the boolean value (True and False or False or True ...) efficiently ? 如何操作它们并有效地找到布尔值(True和False或False或True ...)?
I know and has more precedence than or. 我知道并且比或具有更高的优先级。 So I know about the way where we break the list about every or and take or of booleans computed from each list.
因此,我知道了我们如何打破每个列表的和从每个列表计算出的布尔值的布尔值的方式。
I want to know is there a more easy way to do so ? 我想知道还有更简单的方法吗?
if my_list = [True, "and", False, "or", False, "or", True ] this will output
True as (True and False) or False or True = False or False or True which is True.
if my_list = [True, "and", True, "or", False, "or", False ] this will output
True as (True and True) or False or False = True or False or False which is True
if my_list = [False, "or", False, "and", False, "and", True ] = False or False which is False
One way to do operator precedence is through the shunting-yard algorithm , which requires a stack: 运算符优先级的一种方法是通过调车场算法 ,该算法需要堆栈:
def evaluate(e):
ops = {'and': 1, 'or': 0}
op_stack = []
output = []
for i in e:
if i in ops:
while op_stack and ops[op_stack[-1]] > ops[i]:
output.append(op_stack.pop())
op_stack.append(i)
else:
output.append(i)
op_stack.reverse()
output.extend(op_stack)
stack = []
for i in output:
#print(stack, i)
if i in ops:
a, b = stack.pop(), stack.pop()
if i == 'and':
i = a and b
else:
i = a or b
stack.append(i)
return stack[0]
>>> evaluate([True, "and", False, "or", False, "or", True])
True
>>> evaluate([True, 'or', True, 'and', False])
True
The other way to do operator precedence is a recursive precedence climbing algorithm: 进行运算符优先级的另一种方法是递归优先级爬升算法:
ops = {'and': 1, 'or': 0}
def tokenizer(l):
for i in l:
o = yield i
while o:
yield None
o = yield o
def evaluate(token, prec=0):
lhs = next(token)
while True:
op = next(token, None)
if op is None or ops[op] < prec:
if op: token.send(op)
break
rhs = evaluate(token, ops[op]+1)
#print(lhs, op, rhs)
lhs = lhs and rhs if op == 'and' else lhs or rhs
return lhs
>>> evaluate(tokenizer([True, 'or', True, 'and', False]))
True
>>> evaluate(tokenizer([True, "and", False, "or", False, "or", False, "or",
... True, "and", False, "or", False, "or", False]))
False
With the prints: 与印刷品:
>>> evaluate(tokenizer([True, "and", False, "or", False, "or", False, "or",
... True, "and", False, "or", False, "or", False]))
True and False
False or False
False or False
True and False
False or False
False or False
False or False
False
IIUC you could use map
, isinstance
: IIUC您可以使用
map
, isinstance
:
l = [True, "and", False, "or", False, "or", True]
res = list(map(lambda x: isinstance(x, bool), l))
print(res)
[True, False, True, False, True, False, True]
Not sure if this will be faster, but: 不知道这是否会更快,但是:
l = [True, "and", False, "or", False, "or", False, "or", True, "and", False, "or", False, "or", False]
eval(' '.join([ str(z) for z in l]))
result: 结果:
False
If I understand correctly this should be the simplest (less elegant) solution 如果我正确理解,这应该是最简单(不太优雅)的解决方案
expression = [True, "and", False, "or", False, "or", True]
def eval_expr( value1, operator, value2):
if operator == 'and':
return value1 and value2
else:
return value1 or value2
result = None
while len(expression) != 1:
v1 = expression.pop()
op = expression.pop()
v2 = expression.pop()
partial_result = eval_expr(v1, op, v2)
expression.insert(0, partial_result)
result = partial_result
print result
@Iliyan 's answer is correct. @Iliyan的答案是正确的。 Less hacky than me.
没有我那么客气。
I came up with a trick to do so. 我想出了一个办法。
my_list = [True, "and", False, "or", False, "or", True] my_list = [True,“和”,False,“或”,False,“ or”,True]
Kind of a hack ;) 有点黑客;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.