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

Boolean Expression Elevator Between Two Dictionaries

这是我第一次 post 在这里,我希望我的问题很清楚并且格式正确...

我有两本字典。第一本字典包含我所说的 "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 的选项作为键以及它们是否是 "Accepted" 或 "Rejected" 作为值:

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'}

我将如何评估来自 dict1 的表达式作为 TrueFalse 以确定根据来自 dict2 的选项是否被接受或拒绝了?

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

((1 OR 1 OR 0) AND NOT 1) 计算结果为 False

((0 AND 0) XOR 1) 计算结果为 True

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

我正在应用布尔逻辑:

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

或:如果任何一方为真,则为真

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

异或:如果一侧为真则为真(但是 不是两者)

这是我想出的解决方案。它假定您已经将 'Accepted' 和 'Rejected' 替换为 True 和 False(或者 1 和 0,就像您在问题中所说的那样。)

这将处理结果。它首先将结果格式化为有效的 Python 代码('xor' -> ^、'AND' -> and 和 'OR' -> or),将 opt 值替换为其对应的布尔值,最后使用 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,但我认为这是这种情况下最快的解决方案。

只需稍微修改一下数据,您就可以将其变为有效 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