我知道itertools,但似乎只能生成排列而不能重复。
例如,我想为2个骰子生成所有可能的骰子骰。所以我需要大小为2的[1、2、3、4、5、6]的所有排列,包括重复:(1、1),(1、2),(2、1)...等等
如果可能的话,我不想从头开始实现
Answers:
您在寻找笛卡尔乘积。
在数学中,笛卡尔乘积(或乘积集)是两组的直接乘积。
在您的情况下,这将是{1, 2, 3, 4, 5, 6}
x {1, 2, 3, 4, 5, 6}
。
itertools
可以帮助您:
import itertools
x = [1, 2, 3, 4, 5, 6]
[p for p in itertools.product(x, repeat=2)]
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 3),
(2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6),
(4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3),
(5, 4), (5, 5), (5, 6), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)]
要获得随机骰子掷骰(以完全无效的方式):
import random
random.choice([p for p in itertools.product(x, repeat=2)])
(6, 3)
在python 2.7和3.1中有一个itertools.combinations_with_replacement
功能:
>>> list(itertools.combinations_with_replacement([1, 2, 3, 4, 5, 6], 2))
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 2), (2, 3), (2, 4),
(2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4, 4), (4, 5), (4, 6),
(5, 5), (5, 6), (6, 6)]
(2, 1)
,(3, 2)
,(3, 1)
和类似的......总之它忽略了所有的组合,其中第二卷是低于第一。
在这种情况下,不需要列表理解。
给定
import itertools as it
seq = range(1, 7)
r = 2
码
list(it.product(seq, repeat=r))
细节
显然,笛卡尔积可以生成排列的子集。但是,它遵循:
product
置换置换n r
[x for x in it.product(seq, repeat=r)]
排列无替换,n!
[x for x in it.product(seq, repeat=r) if len(set(x)) == r]
# Equivalent
list(it.permutations(seq, r))
因此,所有组合功能都可以通过以下方式实现product
:
combinations_with_replacement
从实施 product
combinations
从实现permutations
,可以通过实现product
(见上文)我想,我发现只有用一个解决方案lambdas
,map
和reduce
。
product_function = lambda n: reduce(lambda x, y: x+y, map(lambda i: list(map(lambda j: (i, j), np.arange(n))), np.arange(n)), [])
本质上,我正在映射给定一行的第一个lambda函数,迭代columnns
list(map(lambda j: (i, j), np.arange(n)))
然后将其用作新lambda函数的输出
lambda i:list(map(lambda j: (i, j), np.arange(n)))
映射到所有可能的行
map(lambda i: list(map(lambda j: (i, j), np.arange(n))), np.arange(m))
然后将所有结果列表简化为一个。
也可以使用两个不同的数字。
prod= lambda n, m: reduce(lambda x, y: x+y, map(lambda i: list(map(lambda j: (i, j), np.arange(m))), np.arange(n)), [])
random.randint
将更加简单有效。