两个字典之间的布尔表达式Elevator

时间:2017-05-25 00:27:41

标签: python python-3.x boolean-logic boolean-expression

这是我在这里发表的第一篇文章,我希望我的问题清晰,格式正确......

我有两本词典。第一本字典包含我正在调用的内容" Option Expressions"作为值的键和任意项:

dict1 = {'((opt1 OR opt4 OR opt6) AND NOT opt7)': 'Yellow Roof', '((opt2 AND opt3) XOR opt5': 'Purple Scooter'}

print(dict1)

{'((opt1 OR opt4 OR opt6) AND NOT opt7)': 'Yellow Roof',
'((opt2 AND opt3) XOR opt5': 'Purple Scooter'}

第二个字典包含来自dict1的选项作为键,以及它们是否为"接受"或"被拒绝"作为价值观:

dict2 = {'opt1': 'Accepted', 'opt2': 'Rejected', 'opt3': 'Rejected','opt4': 'Accepted', 'opt5': 'Accepted', 'opt6': 'Rejected','opt7': 'Accepted'}

print(dict2)

{'opt1': 'Accepted',
 'opt2': 'Rejected',
 'opt3': 'Rejected',
 'opt4': 'Accepted',
 'opt5': 'Accepted',
 'opt6': 'Rejected',
 'opt7': 'Accepted'}

我如何评估dict1TrueFalse的表达式,以确定根据dict2中的选项是否选择了哪些项目?接受还是拒绝?

我最初的想法是将表达式中的opt替换为1表示接受,0表示拒绝表示:

((1 OR 1 OR 0) AND NOT 1)评估为False

((0 AND 0) XOR 1)评估为True

我一直在对pyparsing进行一些研究,并认为它在这里很有用,尽管我并不完全确定如何最好地利用它。

我正在应用布尔逻辑:

AND:当且仅当双方都是真的时才为真

OR:如果任何一方都是真的,则为真

NOT /(AND NOT):将true更改为false,将false更改为true

XOR:如果一方是真的那么是真的(但是  两者)

2 个答案:

答案 0 :(得分:1)

通过对数据进行一点点按摩,您可以将其转换为有效的Python并让Python解释器进行出价:

# Mandatory warning here about using eval() - here be dragons!

dict1 = {"((opt1 OR opt4 OR opt6) AND NOT opt7)": "Yellow Roof",
         "((opt2 AND opt3) XOR opt5)": "Purple Scooter"}

dict2 = {"opt1": "Accepted",
         "opt2": "Rejected",
         "opt3": "Rejected",
         "opt4": "Accepted",
         "opt5": "Accepted",
         "opt6": "Rejected",
         "opt7": "Accepted"}

# lets first normalize the 'opt' codes to True/False
dict2_norm = {k: (True if v == "Accepted" else False) for k, v in dict2.items()}

# Now all we need to do is evaluate the expressions:
for expression, value in dict1.items():
    # Let's first normalize the expression to Python-digestible
    expression = expression.replace("XOR", "is not").replace("OR", "or")\
        .replace("AND", "and").replace("NOT", "not")
    if eval(expression, dict2_norm):
        print(value)

# prints: Purple Scooter

答案 1 :(得分:0)

这是我提出的解决方案。它假设你已经用True和False替换了'Accepted'和'Rejected'(或者像你在问题中所说的那样替换了1和0)。

然后处理结果。它首先将结果格式化为有效的Python代码('xor' - > ^,'AND' - > and和'OR' - > or),替换使用布尔对应物选择值,最后使用eval内置函数计算表达式。

input_code = '((opt1 OR opt4 OR opt6) AND NOT opt7)'
input_w_xor = '(opt2 AND opt3) XOR opt5'
result_codes = {'opt1': True, 'opt2': False, 'opt3': False,'opt4': True, 'opt5': True, 'opt6': False,'opt7': True}


def process_code(input_code, result_codes):
    input_code = input_code.lower()

    def replace_op_codes(code):
        for opt_key, opt_value in result_codes.items():
            code =  code.replace(opt_key, str(opt_value))
        return code

    input_code = replace_op_codes(input_code)
    input_code = input_code.replace("xor", '^')
    result = eval(input_code)

    return result


print(process_code(input_code, result_codes))
print(process_code(input_w_xor, result_codes))

我倾向于回避使用evalexec,但我认为这是这种情况下最快的解决方案。