【发布时间】:2019-08-11 23:46:17
【问题描述】:
假设我有一个如下所示的有效负载:
payload = {
"OR": [
{
"AND" : [[1,2,3],[3,4]]
}, # ([1,2,3] AND [3,4]) --> [3]
{
"OR" : [
{
"AND" : [
{
"OR" : [[10,11],[12,13]]
}, # ([10,11] OR [12,13]) ---> [10,11,12,13]
{
"AND": [[11,13]]
} # ([11,13]) ---> [11,13]
]
}, # ([10,11,12,13] AND [11,13]) ---> [11,13]
{
"AND" : [[14,15],[15]]
} # ([14,15] AND [15]) ---> [15]
]
} # ([11,13] OR [15]) ---> [11,13,15]
]
} # ([3] OR [11,13,15]) ---> [3,11,13,15]
此时我可以使用字符串 AND 和 OR 作为布尔运算符,感觉好像它们分别映射到 set.intersection() 和 set.union()。
我已经在嵌套bool_operator:[...] 块的字典中评论了每个“块”将如何根据运算符减少。
鉴于这一切,我想将此有效负载减少到以下内容:
[3,11,13,15]
我知道这需要递归,为此,我创建了一个函数,可以在给定纯文本布尔运算符的情况下减少列表列表:
from functools import reduce
def reduce_block(bool_operator, block):
bool_operator_set_hash = {
'AND':'intersection',
'OR':'union'
}
return reduce(
lambda x,y: getattr(set(x),bool_operator_set_hash.get(bool_operator.upper()))(set(y)),
block
)
这适用于单个布尔运算符和包含值的列表列表。但是,我在递归方面遇到了麻烦。有什么建议么?我是否过于复杂了?想把它变成一个整洁的库以供使用。
非常感谢您提供任何见解。
2019 年 8 月 12 日更新
@Ajax1234 的解决方案效果很好,直到我遇到给定布尔运算符有 > 2 个块的情况,例如
payload = {'OR': [
{'AND': [
[
('5657',),
('5698',)
]
]
},
{'AND': [
[
('6101',),
('5420',),
('5334',),
('5439',)
]
]
},
{'AND': [
[
('5802',),
('6005',),
('6675',),
('5878',)
]
]
},
{'AND': [
[
('6265',),
('6157',),
('6238',),
('6189',),
('6191',)
]
]
}
]
}
更新要求:理想情况下也可以在上述有效负载上工作。
2019 年 8 月 13 日更新
仍然遇到边缘情况,例如以下载荷:
payload = {
'AND': [
{
'OR': [
[('6101',)],
[('6265',)]
]
}
]
}
在这种情况下,我的输出是单值集:{'OR'},尽管我希望是 {('6101',),('6265',)}。感谢您到目前为止@ajax1234 的帮助,有什么建议吗?
【问题讨论】:
-
你需要
bool_operator做什么? -
@Samha',
bool_operator用于从set实例中获取方法;需要允许AND和OR之类的字符串,但需要来自set的方法。
标签: python algorithm recursion reduce