两个列表中所有组件的所有排列

All permutations of all components from two lists

提问人:Nick 提问时间:10/31/2023 更新时间:10/31/2023 访问量:63

问:

operators = ['+', '-', 'x']
numbers = [4,5,6,9]

如何从两个列表中创建所有可能公式的可能排列列表?

即 4+5-6x9、4-5+6x9,...,9-4+5x6....

对于每个公式,不能使用重复项。尝试了各种迭代工具,但还没有弄清楚这个。

Python 排列

评论

4赞 Scott Hunter 10/31/2023
您忘记发布解决此问题的尝试。
0赞 Scott Hunter 10/31/2023
可以包含重复项或包含重复项吗?operatorsnumbers

答:

2赞 pho 10/31/2023 #1

没有一个函数可以做到这一点。你需要分别计算运算符和数字的排列,然后你需要得到两组排列的笛卡尔积:itertools

from itertools import permutations, product
operators = ['+', '-', 'x']
numbers = [4,5,6,9]

all_expressions = set()

for nums, ops in product(permutations(numbers), permutations(operators)):
    expr = "".join(f"{n}{o}" for n, o in zip(nums, ops)) + str(nums[-1])
    all_expressions.add(expr)

作为一个集合创建会为您处理重复项。这给出了一个包含 144 个元素的集合,正如预期的那样:all_expressions

{'4+5-6x9',
 '4+5-9x6',
 '4+5x6-9',
 '4+5x9-6',
 '4+6-5x9',
 ...
 '9x5-6+4',
 '9x6+4-5',
 '9x6+5-4',
 '9x6-4+5',
 '9x6-5+4'}

permutations(numbers)计算列表的所有可能顺序。同样,计算列表的所有可能顺序。numberspermutations(operators)operators

在每次迭代中,这两件事会产生一个 (in the variable ) 和一个 order of (in the variable)。productnumbersnumsoperatorsops

例如,在第一次迭代中,和 .现在,我们使用它们来构建表达式。 给出任一元组的相应元素,我们将其并排格式化为字符串,因此生成器表达式生成字符串 、 和 。 然后连接所有这些字符串。最后,将 的最后一个元素连接到生成的字符串。最终表达式将添加到包含所有表达式的集合中。nums = (4, 5, 6, 9)ops = ('+', '-', 'x')zip(nums, ops)f"{n}{o}" for ...'4+''5-''6x'"".join(...)nums

然后我们冲洗并重复。

评论

0赞 Yaakov Bressler 10/31/2023
很棒的解决方案!我认为,如果您的解决方案分解为 2 个离散步骤,对初学者会更有帮助:1) 获取 nums + 运算符的所有排列(例如:)......然后 2) 这些组合的所有排列4+6(X+Y){op}(Z-Y)
1赞 pho 10/31/2023
@YaakovBressler这并不完全是这个解决方案的作用,我很快就会在解释中添加一些更详细的内容
1赞 pho 10/31/2023
@YaakovBressler. 是,然后所有这些内容都会被连接起来。 并包含数字/运算符的不同排列,这些数字/运算符来自 和 的排列乘积{n}4|5|6f"{n}{o}"4+|5-|6xnumsopsnumbersoperators
0赞 Yaakov Bressler 10/31/2023
TY为您的详细回复。
4赞 Kelly Bundy 10/31/2023 #2
from itertools import permutations

operators = ['+', '-', 'x']
numbers = [4,5,6,9]

formulas = [
    ''.join(a)
    for a in [[None] * 7]
    for a[::2] in permutations(map(str, numbers))
    for a[1::2] in permutations(operators)
]

print(formulas)

结果(在线尝试!

['4+5-6x9', '4+5x6-9', '4-5+6x9', '4-5x6+9', '4x5+6-9', '4x5-6+9',
 '4+5-9x6', ...,
 ...
 '9+6-5x4', '9+6x5-4', '9-6+5x4', '9-6x5+4', '9x6+5-4', '9x6-5+4']

评论

0赞 pho 10/31/2023
不错的解决方案!我从未见过在列表推导器中创建的列表被更深层次的循环修改,我今天学到了一个新技巧:)
0赞 Kelly Bundy 10/31/2023
@pho是的,我喜欢做/分享这样的诡计。还有我修改列表的方式,我认为只有少数人知道我们可以使用切片作为目标(尽管这很少有用,这可能是我几乎从未见过其他人这样做的更大原因)。for
0赞 Matthias 10/31/2023
代码有点不可读(没有冒犯),但它显示了一个 Python 大师在工作。
0赞 Kelly Bundy 10/31/2023
@Matthias嗯,自从我写它以来,我当然有偏见,但我相信如果其他人写了它,我会毫不费力地阅读它。这真的很简单。一个比帮助更好的名字吗?我考虑过,但懒得下定决心,对现在的方式很满意。abuffertemplate
0赞 Matthias 10/31/2023
要理解这些以切片为目标的嵌套循环需要一些时间,而且由于您不经常看到这种代码,因此确实需要一些时间——至少对我来说是这样。for