提问人:Nick 提问时间:10/31/2023 更新时间:10/31/2023 访问量:63
两个列表中所有组件的所有排列
All permutations of all components from two lists
问:
operators = ['+', '-', 'x']
numbers = [4,5,6,9]
如何从两个列表中创建所有可能公式的可能排列列表?
即 4+5-6x9、4-5+6x9,...,9-4+5x6....
对于每个公式,不能使用重复项。尝试了各种迭代工具,但还没有弄清楚这个。
答:
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)
计算列表的所有可能顺序。同样,计算列表的所有可能顺序。numbers
permutations(operators)
operators
在每次迭代中,这两件事会产生一个 (in the variable ) 和一个 order of (in the variable)。product
numbers
nums
operators
ops
例如,在第一次迭代中,和 .现在,我们使用它们来构建表达式。 给出任一元组的相应元素,我们将其并排格式化为字符串,因此生成器表达式生成字符串 、 和 。 然后连接所有这些字符串。最后,将 的最后一个元素连接到生成的字符串。最终表达式将添加到包含所有表达式的集合中。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|6
f"{n}{o}"
4+|5-|6x
nums
ops
numbers
operators
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嗯,自从我写它以来,我当然有偏见,但我相信如果其他人写了它,我会毫不费力地阅读它。这真的很简单。一个比帮助更好的名字吗?我考虑过,但懒得下定决心,对现在的方式很满意。a
buffer
template
0赞
Matthias
10/31/2023
要理解这些以切片为目标的嵌套循环需要一些时间,而且由于您不经常看到这种代码,因此确实需要一些时间——至少对我来说是这样。for
评论
operators
numbers