如何避免为交换运算符生成相同的表达式



我想从一组变量和运算符开始构建一组所有可能的表达式。但是,我不想同时生成"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']

最新更新