如何在python中生成数组的排列?

如何在python中生成数组的排列?,python,permutation,Python,Permutation,我有一个27个元素的数组,我不想生成数组的所有排列(27!) 我需要5000个随机选择的排列,任何提示都会有用…。它是一个生成器,所以它不会创建整个排列列表。您可以随机跳过,直到有5000个为止。您可能需要itertools.permutations()函数。一定很喜欢itertools模块 注:2.6中新增 import random perm_list = [] for i in range(5000): temp = range(27) random.shuffle(t

我有一个27个元素的数组,我不想生成数组的所有排列(27!)
我需要5000个随机选择的排列,任何提示都会有用…

。它是一个生成器,所以它不会创建整个排列列表。您可以随机跳过,直到有5000个为止。

您可能需要itertools.permutations()函数。一定很喜欢itertools模块

注:2.6中新增

import random

perm_list = []

for i in range(5000):
    temp = range(27)
    random.shuffle(temp)
    perm_list.append(temp)

print(perm_list)
10888869450418352160768000000
我喜欢大数字!:)

10888869450418352160768000001
是主要的

编辑:

#with duplicates check as suggested in the comment

perm_list = set()
while len(perm_list)<5000:
    temp = range(27)
    random.shuffle(temp)
    perm_list.add(tuple(temp)) # `tuple` because `list`s are not hashable. right Beni?

print perm_list
#按照注释中的建议检查重复项
perm_list=set()

而len(perm_list)要生成一个置换,请使用并存储结果的副本。在循环中重复此操作,每次检查是否有重复项(但可能不会有重复项)。一旦结果集中有5000项,请停止

为了解决注释中的问题,Python基于,其周期为
2**19937-1
,大大大于
27因此它应该适合您的使用

# apermindex should be a number between 0 and factorial(len(alist))
def perm_given_index(alist, apermindex):
    for i in range(len(alist)-1):
        apermindex, j = divmod(apermindex, len(alist)-i)
        alist[i], alist[i+j] = alist[i+j], alist[i]
    return alist
用法:
perm\u给定索引(['a','b','c'],3)


这将使用排列的莱默码作为匹配的
j
值。

您可以尝试实现
随机排列。为了方便起见,我使用了第三方库,该库为我们实现了以下配方:

import more_itertools as mit

iterable = range(27)
mit.random_permutation(iterable)
# (24, 3, 18, 21, 17, 22, 14, 15, 20, 8, 4, 7, 13, 6, 25, 5, 12, 1, 9, 19, 23, 11, 16, 0, 26, 2, 10)
为函数的每次调用创建一个随机排列。我们可以制作一个生成器,为
n
调用生成这些结果。我们将实现此生成器,并用一个简化示例演示随机结果:

def random_permute_generator(iterable, n=10):
    """Yield a random permuation of an iterable n times."""
    for _ in range(n):
        yield mit.random_permutation(iterable)

list(random_permute_generator(range(10), n=20))
# [(2, 7, 9, 6, 5, 0, 1, 3, 4, 8),
#  (7, 3, 8, 1, 2, 6, 4, 5, 9, 0),
#  (2, 3, 1, 8, 7, 4, 9, 0, 6, 5),
#  (0, 5, 6, 8, 2, 3, 1, 9, 4, 7),
#  (0, 8, 1, 9, 4, 5, 7, 2, 3, 6),
#  (7, 2, 5, 8, 3, 4, 1, 0, 9, 6),
#  (9, 1, 4, 5, 8, 0, 6, 2, 7, 3),
#  (3, 6, 0, 2, 9, 7, 1, 4, 5, 8),
#  (8, 4, 0, 2, 7, 5, 6, 1, 9, 3),
#  (4, 9, 0, 5, 7, 1, 8, 3, 6, 2)
#  ...]
对于您的特定问题,请使用适当的值替换iterable和调用次数
n
,例如
random\u permute\u generator(iterable,n=5000)

有关此工具的更多信息,请参见


详细信息

对于那些感兴趣的人,这里是实际的配方

从:


这并不是真正的“随机”,因为itertools以定义的顺序创建它们,并且有有限数量的排列。更好的做法是:(1)确定有多少个置换(称这个数字为
N
),(2)然后在
0..N-1
范围内生成5000个不同的随机索引,(3)从itertools.permutations生成器中选择对应于这些索引的置换。是的,我知道这不是最好的。我第一次读这个问题时,不知怎么的,我没有注意到“随机选择”的部分。我不会删除它,也许有人在搜索“如何在python中生成数组排列?”时会发现它很有用。@Cat Plus这就是我:d这太慢了-他说他有27个元素。可能值得一提的是
27
为10888869450418352160768000000.+1,但请注意,
random.shuffle
有一个严重的缺点:随着n的增大,大多数RNG的周期小于置换总数。这意味着对于一个足够大的n,几乎所有可能的排列都无法生成,所以这不是真正的随机排列。Python的随机生成器的周期为2**19937-1,所以它可能已经足够好了。另一个挑剔之处是,对于真正的随机数,您需要一个真正的随机源(例如,来自放射性衰变),Python的随机模块只提供伪随机数。但在通常情况下,当人们说“随机”时,他们真正的意思是“伪随机”,我想这就是海报上的意思!这是一个有10888869450418352160768000000张脸的大骰子,其中任何一张脸出现的概率是1/10888869450418352160768000000。不可能@PratikDeoghare这是一个面数为6002位的大模具,但它以特定的、已知的模式旋转,并且面载荷上的面数相同。以“是”的方式复制。其中任何一个与另一个相等的概率为
1/10888869450418352160768000000
,但它们都不相同的概率更大。例如,如果您选择
27+1
排列,即使其中一个与另一个相等的概率很小,没有重复的概率也为0。在这种情况下,beacause 27!>>5000,至少有一个重复的概率是
(1/27)*5000
。仍然很小,但不一样。要按照Mark的建议检查重复项,请使用
perms=set()
perms.add(tuple(temp))
,和
,而len(perms)<5000
,而不是for循环。@Beni起初我没有遵循你的
tuple(temp)
建议,但后来我明白我是个傻瓜!!谢谢你,伙计!如果您需要存储大量置换以使用整数表示,这可能非常适合压缩。受到编写Lehmer编码(和解码)的启发,应该在核心python中有所体现——至少作为itertools的一部分。任何与置换有关的工作都需要一种与相关的莱默索引进行转换的方法。
def random_permutation(iterable, r=None):
    "Random selection from itertools.permutations(iterable, r)"
    pool = tuple(iterable)
    r = len(pool) if r is None else r
    return tuple(random.sample(pool, r))