根据逻辑表达式计算嵌套列表的所有组合
Calculating all combinations of nested lists based on logical expression
假设我有一个动作列表,其中可以包含三种不同类型的动作:
类型A:可以包含所有类型的动作(析取)
B类:可以包含所有类型的动作(有序连词)
类型 C:不能包含子动作。这是我最后想要的水平。
我想过(基于:python - representing boolean expressions with lists)析取和合取可以用一个元组分别表示一个列表,但我不确定这是否是一个最优解。
对于类型A和B,有一个包含类型元素的字典,例如
type_a = {
‘a1’: ('b1', 'a2'),
‘a2’: ('c1', 'c2')
}
type_b = {
‘b1’: ['c4', 'c5', 'c7'],
‘b2’:['c3', 'c4']
}
详细解释:
‘a1’等于('b1', 'a2')
,等于(['c4', 'c5','c7'], 'c1', 'c2')
‘a2’等于('c1', 'c2')
‘b1’等于['c4', 'c5', 'c7']
‘b2’等于['c3', 'c4']
示例输入:
['a1', 'b2', 'c6']
预期输出:
结果应仅包含 C 类操作。
原始
[(['c4', 'c5', 'c7'], 'c1', 'c2'), 'c3', 'c4', 'c6']
所有组合
['c4', 'c5','c7', 'c3', 'c4', 'c6']
['c1', 'c3', 'c4', 'c6']
['c2', 'c3', 'c4', 'c6']
问题:
- 元组和列表的合取和析取表示是个好主意吗?
- 实现这个的有效方法是什么?
- 是否有可能实现计算的功能
所有组合,与 itertools? (我不是很熟悉
他们,但我听说他们很强大)
感谢您的帮助。
Python 中还有一个 set type 支持集合操作 - 如果您不关心排序。
遗憾的是,itertools 在这里没有多大帮助。然而,以下递归野兽似乎可以完成这项工作:
def combinations(actions):
if len(actions)==1:
action= actions[0]
try:
actions= type_a[action]
except KeyError:
try:
actions= type_b[action]
except KeyError:
#action is of type C, the only possible combination is itself
yield actions
else:
#action is of type B (conjunction), combine all the actions
for combination in combinations(actions):
yield combination
else:
#action is of type A (disjunction), generate combinations for each action
for action in actions:
for combination in combinations([action]):
yield combination
else:
#generate combinations for the first action in the list
#and combine them with the combinations for the rest of the list
action= actions[0]
for combination in combinations(actions[1:]):
for combo in combinations([action]):
yield combo + combination
想法是为第一个动作 ('a1'
) 生成所有可能的值,并将它们与其余动作 (['b2', 'c6']
) 的(递归生成的)组合组合起来。
这也消除了用列表和元组表示合取和析取的需要,老实说,我觉得这很混乱。
假设我有一个动作列表,其中可以包含三种不同类型的动作:
类型A:可以包含所有类型的动作(析取)
B类:可以包含所有类型的动作(有序连词)
类型 C:不能包含子动作。这是我最后想要的水平。
我想过(基于:python - representing boolean expressions with lists)析取和合取可以用一个元组分别表示一个列表,但我不确定这是否是一个最优解。
对于类型A和B,有一个包含类型元素的字典,例如
type_a = {
‘a1’: ('b1', 'a2'),
‘a2’: ('c1', 'c2')
}
type_b = {
‘b1’: ['c4', 'c5', 'c7'],
‘b2’:['c3', 'c4']
}
详细解释:
‘a1’等于('b1', 'a2')
,等于(['c4', 'c5','c7'], 'c1', 'c2')
‘a2’等于('c1', 'c2')
‘b1’等于['c4', 'c5', 'c7']
‘b2’等于['c3', 'c4']
示例输入:
['a1', 'b2', 'c6']
预期输出:
结果应仅包含 C 类操作。
原始
[(['c4', 'c5', 'c7'], 'c1', 'c2'), 'c3', 'c4', 'c6']
所有组合
['c4', 'c5','c7', 'c3', 'c4', 'c6']
['c1', 'c3', 'c4', 'c6']
['c2', 'c3', 'c4', 'c6']
问题:
- 元组和列表的合取和析取表示是个好主意吗?
- 实现这个的有效方法是什么?
- 是否有可能实现计算的功能 所有组合,与 itertools? (我不是很熟悉 他们,但我听说他们很强大)
感谢您的帮助。
Python 中还有一个 set type 支持集合操作 - 如果您不关心排序。
遗憾的是,itertools 在这里没有多大帮助。然而,以下递归野兽似乎可以完成这项工作:
def combinations(actions):
if len(actions)==1:
action= actions[0]
try:
actions= type_a[action]
except KeyError:
try:
actions= type_b[action]
except KeyError:
#action is of type C, the only possible combination is itself
yield actions
else:
#action is of type B (conjunction), combine all the actions
for combination in combinations(actions):
yield combination
else:
#action is of type A (disjunction), generate combinations for each action
for action in actions:
for combination in combinations([action]):
yield combination
else:
#generate combinations for the first action in the list
#and combine them with the combinations for the rest of the list
action= actions[0]
for combination in combinations(actions[1:]):
for combo in combinations([action]):
yield combo + combination
想法是为第一个动作 ('a1'
) 生成所有可能的值,并将它们与其余动作 (['b2', 'c6']
) 的(递归生成的)组合组合起来。
这也消除了用列表和元组表示合取和析取的需要,老实说,我觉得这很混乱。