data={
"or":{
"=":{
"name": ["aaa", "bbb"]
},
">": {
"age": [1, 2, 3]
}
}
}
字典结构类似于lisp的那种结构(+ 2 3 (× 4 5))前缀表示法
然后把这种嵌套的结构,解析成还原成一般的结构,字符串,像这样。
“name = aaa or name = bbb or age > 1 or age > 2 or age > 3”
也许实际用不到这么复杂的结构。
可以参考一下json格式解析的代码
这个还算能用。
def flatten(nested):
for k,v in nested.items():
try:
yield [(' '+k+' ').join(x) for x in flatten(v)]
except AttributeError: // list 没有 items 方法
for i in v:
yield [k,i]
data={
"or":{
"like":{
"name": ["aaa", "bbb"]
}
}
}
print list(flatten(data))
>>>[['name like aaa or name like bbb']]
超过三层嵌套貌似就不行了?
就算每种操作符的处理方式都不一样的也没关系,只要往rator_handler
里添加新的处理方式就行了。
编辑:添加了infix的排版方式。
import functools
def to_sexpr(ast):
if isinstance(ast, (int, basestring)):
return ast
elif isinstance(ast, dict):
rator, = ast.keys()
children, = ast.values()
return rator_handler[rator](rator, children)
else:
assert 0, 'Not a valid ast: %r' % ast
def handle_binary(rator, children):
lhs, rhs = map(singleton_dict, children.items())
return (rator, to_sexpr(lhs), to_sexpr(rhs))
def singleton_dict((k, v)):
return {k: v}
def handle_multiary_join_or(rator, children):
lhs, = children.keys()
rhss, = children.values()
exprs = [(rator, lhs, to_sexpr(rhs)) for rhs in rhss]
return functools.reduce(mk_binary_or, exprs)
def mk_binary_or(a, b):
return ('or', a, b)
# Add other operator handlers here
rator_handler = {
'or': handle_binary,
'>': handle_multiary_join_or,
'=': handle_multiary_join_or
}
def ppr_sexpr(e):
if isinstance(e, (int, basestring)):
return str(e)
elif isinstance(e, tuple):
return '(%s)' % ' '.join(map(ppr_sexpr, e))
else:
assert 0, 'Not a valid expr: %r' % e
def ppr_infix(e):
if isinstance(e, (int, basestring)):
return str(e)
elif isinstance(e, tuple):
rator = e[0]
if rator == 'or':
lhs, rhs = e[1:]
return '%s %s %s' % (ppr_infix(lhs), rator, ppr_infix(rhs))
elif rator in ('>', '='):
lhs, rhs = e[1:]
return '%s %s %s' % (ppr_infix(lhs), rator, ppr_infix(rhs))
else:
assert 0, 'Dont know how to ppr_infix: %r' % e
else:
assert 0, 'Not a valid expr: %r' % e
def test():
data = {
'or': {
'=': {
'name': ['aaa', 'bbb']
},
'>': {
'age': [1, 2, 3]
}
}
}
e = to_sexpr(data)
print(ppr_infix(e))
# => name = aaa or name = bbb or age > 1 or age > 2 or age > 3
if __name__ == '__main__':
test()