假设我有这个列表:
[2,3,5,7]
我想输出所有乘法组合:
[6,10,14,15,21,35,30,42,105,210]
有没有一个Python一行代码的解决方案?
假设我有这个列表:
[2,3,5,7]
我想输出所有乘法组合:
[6,10,14,15,21,35,30,42,105,210]
有没有一个Python一行代码的解决方案?
>>> from numpy import prod
>>> from itertools import combinations
>>> lst = [2,3,5,7]
>>> [prod(x) for i in range(2, len(lst)+1) for x in combinations(lst, i)]
[6, 10, 14, 15, 21, 35, 30, 42, 70, 105, 210]
reduce(lambda x, y: x * y, numbers)
。 - Maxime Roussin-Bélangernumpy
。 - ᴀʀᴍᴀɴnumpy.prod
是可行的,但我认为它更难阅读。如果你不能使用 numpy,reduce(或编写自己的 prod 函数)是有效的备选方案。 - timgebreduce
不难理解,但也许你是对的。 - ᴀʀᴍᴀɴreduce
表达式中实际上不需要 lambda 函数,因为它已经存在:reduce(int.__mul__, numbers)
,但是,当然,您必须确保在此处使用的是整数。 - Thomas BaruchelItertools是一个很好的选择。作为另一种解决方案,可以使用纯numpy(所有0,1,...,n项的乘积):
from numpy import *
a,n=array(l),len(l)
where(bitwise_and.outer(arange(2**n),2**arange(n))>0,a,1).prod(1)
#array([ 1, 2, 3, 6, 5, 10, 15, 30, 7, 14, 21, 42, 35, 70, 105, 210])
在大型列表上速度提高了多达40倍。
一些解释:
bitwise_and.outer(arange(2**n),2**arange(n))
是
array([[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 2, 0, 0],
[1, 2, 0, 0],
[0, 0, 4, 0],
[1, 0, 4, 0],
[0, 2, 4, 0],
[1, 2, 4, 0],
[0, 0, 0, 8],
[1, 0, 0, 8],
[0, 2, 0, 8],
[1, 2, 0, 8],
[0, 0, 4, 8],
[1, 0, 4, 8],
[0, 2, 4, 8],
[1, 2, 4, 8]], dtype=int32)
where(bitwise_and.outer(arange(2**n),2**arange(n))>0,a,1)
的翻译结果是:
这段代码的作用是将长度为 n 的二进制数列和 2 的 n 次方进行按位与运算,然后判断结果是否大于 0。如果大于 0,则返回 a 数组中对应位置的值,否则返回 1。
array([[1, 1, 1, 1],
[2, 1, 1, 1],
[1, 3, 1, 1],
[2, 3, 1, 1],
[1, 1, 5, 1],
[2, 1, 5, 1],
[1, 3, 5, 1],
[2, 3, 5, 1],
[1, 1, 1, 7],
[2, 1, 1, 7],
[1, 3, 1, 7],
[2, 3, 1, 7],
[1, 1, 5, 7],
[2, 1, 5, 7],
[1, 3, 5, 7],
[2, 3, 5, 7]])
接下来是按行输出prod
。
y=bitwise_and.outer(arange(2**n),2**arange(n))>0; res= where(y,a,1).prod(1)[y.sum(1)>1]
。但是限制在2个或更多操作数上在数学上对我来说很棘手(对计算机也是如此...)。 - B. M.l
中:[ list(l[k] for k in range(len(l))
if (2**k) & (n+(n+n.bit_length()).bit_length()))
for n in range(1,2**len(l)-len(l)) ]
返回您所需的组合(只需将初始列表用一些reduce
包装以执行乘法本身,但棘手的部分在于其中)。 "gem"是n +(n + n.bit_length())。bit_length()
,它将正整数映射到至少包含两个位集(在其二进制展开中),这用于通过确保每次至少取两个成员来选择初始列表的成员。您可以在{{link1:http://oeis.org/A057716}}了解有关此公式的更多信息(我仅适应了先前链接“公式”部分中第一个表达式的Python语法)。
因此,整个答案将是:
[ reduce(int.__mul__,
(l[k] for k in range(len(l))
if (2**k) & (n+(n+n.bit_length()).bit_length())))
for n in range(1,2**len(l)-len(l)) ]
(如果你使用的是Python 3,你需要导入reduce
。)
itertools
了吗? - jonrsharpesorted({a * b for (a, b) in combinations(values, 2)})
- Peter Wood