我想从一组变量和运算符开始构建一组所有可能的表达式。但是,我不想同时生成"a+b"和"b+a",因为它们在数学上是相同的;而"A/B"和"B/A"则不是。我试图区分交换和非交换列表中的运算符,但不知道如何编写避免简并的交换for
循环。
primary_descriptors=['a', 'b']
commutative_operators=['+', '*']
non_commutative_operators=['-','/']
b=[]
for x in primary_descriptors:
for y in commutative_operators:
b.append([x+y+z for z in primary_descriptors if z!=x])
d=[]
for x in primary_descriptors:
for y in non_commutative_operators:
d.append([x+y+z for z in primary_descriptors if z!=x])
flat_list_1 = [item for sublist in b for item in sublist] #from Alex Martelli's answer
flat_list_2 = [item for sublist in d for item in sublist]
print(flat_list_1)
print(flat_list_2)
此代码的输出为
['a+b', 'a*b', 'b+a', 'b*a']
['a-b', 'a/b', 'b-a', 'b/a']
但我只想要 ['a+b', 'a*b'] 在第一行。
itertools
的解决方案。 itertools.permutations
可用于获取两个订单中的所有对,而itertools.combinations
可用于获取所有对,但只能获取一个订单:
>>> from itertools import permutations, combinations
>>> primary_descriptors='abc'
>>> commutative_operators='+*'
>>> non_commutative_operators='-/'
>>>
>>> [op.join(pair) for pair in combinations(primary_descriptors, 2) for op in commutative_operators]
['a+b', 'a*b', 'a+c', 'a*c', 'b+c', 'b*c']
>>> [op.join(pair) for pair in permutations(primary_descriptors, 2) for op in non_commutative_operators]
['a-b', 'a/b', 'a-c', 'a/c', 'b-a', 'b/a', 'b-c', 'b/c', 'c-a', 'c/a', 'c-b', 'c/b']
一个好方法是使用不等式运算符,这将有效地防止"b"在"a"之前:
combinations = []
primary_descriptors=['a', 'b']
commutative_operators=['+', '*']
for x in primary_descriptors:
for y in commutative_operators:
combinations += [(x, y, z) for z in primary_descriptors if x <= z]
print(combinations)
为交换运算符编写循环时,请为所有操作数运行外部循环,但仅对操作数列表中后面的操作数运行内部循环。 像这样的东西,也许...
for x_index, x in enumerate(primary_descriptors):
for y in commutative_operators:
b.append([x+y+z for z in primary_descriptors[x_index+1:] ])
新输出:
['a+b', 'a*b']
['a-b', 'a/b', 'b-a', 'b/a']