我有一本如下形式的词典:

dict = {'a':25, 'ab':3.3, '(cd)': 4, 'ef':35, 'gh':12.2, etc.}

用户输入逗号分隔的短语(搜索字符串),如:

'a > 5, 0 < (cd) < 6, ef < 35'

上面有三个条件,但它可以是任意数量的条件:我想要的是判断我的词典是否满足所有搜索条件.

 if dict meets all conditions:
     do somthing
 else:
     do something else

我可以获取搜索字符串,执行Split(‘,’),循环每个条件,提取关键字、比较运算符(&lt;或&gt;)和数字,并判断我的DICT是否满足所有条件.在上面的示例中,满足dict[‘a’]&gt;5,也满足0;lt;dict[‘(Cd)’]&lt;6,但不满足dict[‘ef’]&lt;35.

有没有更快更优雅的方法来做到这一点?一个更好更聪明的方法来从"a5"到dict [a5]?例如,我可以将我的dict转换为Pandas的嵌套 struct ,并做一些判断吗?除了我正在try 的蛮力方法之外,Python中是否有一种求值方法或类似的方法?

推荐答案

为此构建一个解析器并不困难.您可以使用operator包来处理条件,除此之外,它只是一堆格式化和循环数据.

import operator, re

# dictionary of operators
operators = {'<' :operator.lt,
             '<=':operator.le,
             '==':operator.eq,
             '>=':operator.ge,
             '>' :operator.gt,
             '!=':operator.ne
             }
        
# format operators keys for regex group
_oper = '|'.join(operators.keys())
        
# regex
oper   = re.compile(fr'\s*({_oper})\s*').split
number = re.compile(r'-?\d*(\.\d+)?').fullmatch
string = re.compile(r'("|\')(?P<str>.*)\1').fullmatch

def cast(value:str) -> float|int|bool|str|None:
    out = None
    
    if (v := value.lower()) in ('true', 'false'):
        out = v == "true"
    elif m := string(value):
        out = m.group('str')
    elif m := number(value):
        out = (int,float)['.' in v](v)
        
    return out

def check_conditions(data:dict, conditions:str) -> bool:
    # stores condition results
    facts = []

    for cond in conditions.split(','):
        # stores values and operators
        v, o = [], []
        
        # parse values and operators
        for c in oper(cond):
            if (c := c.strip()) in operators:
                # store operator function
                o.append(operators.get(c))
            else:
                # try data[c] else cast c
                v.append(data.get(c, cast(c)))
              
        # make sure values length is one more than operators              
        if (len(v) - len(o)) != 1:
            raise ValueError
            
        # call all operator functions on values and store results
        facts += [o[i](*v[i:i+2]) for i in range(len(o))]
    
    return all(facts)

usage

data  = {'a':25, 'ab':3.3, '(cd)': 4, 'ef':35, 'gh':.2, 'ij':"hello", 'kl':False, "mn":None}

conds = 'mn==None, a>5, 0<(cd)<5, 35==ef!=34>12<20, ij==\'hello\''  
print(check_conditions(data, conds)) #True

Python相关问答推荐

如何让剧作家等待Python中出现特定cookie(然后返回它)?

从numpy数组和参数创建收件箱

Mistral模型为不同的输入文本生成相同的嵌入

如何使用它?

当递归函数的返回值未绑定到变量时,非局部变量不更新:

mypy无法推断类型参数.List和Iterable的区别

Python导入某些库时非法指令(核心转储)(beautifulsoup4."" yfinance)

如何在Python中使用另一个数据框更改列值(列表)

如何使用OpenGL使球体遵循Python中的八样路径?

如何找出Pandas 图中的连续空值(NaN)?

如何过滤组s最大和最小行使用`transform`'

为用户输入的整数查找根/幂整数对的Python练习

数据框,如果值在范围内,则获取范围和

如何将泛型类类型与函数返回类型结合使用?

极点替换值大于组内另一个极点数据帧的最大值

Django更新视图未更新

递归链表反转与打印语句挂起

解析CSV文件以将详细信息添加到XML文件

Groupby并在组内比较单独行上的两个时间戳

Python键盘模块不会立即检测到按键