首页 文章

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

提问于
浏览
0

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

我有两本词典 . 第一个字典包含我所谓的“选项表达式”作为键和值的任意项:

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是否被接受或拒绝来确定选择了哪些项目?

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

((1 OR 1 OR 0) AND NOT 1) 哪个评价为 False

((0 AND 0) XOR 1) 哪个评价为 True

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

I am applying boolean logic:

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

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

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

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

2 回答

  • 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
    
  • 0

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

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

    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 ,但我认为这是这种情况下最快的解决方案 .

相关问题