Python 生成所有置换的随机子集

Python 生成所有置换的随机子集,python,permutation,itertools,Python,Permutation,Itertools,我正在寻找一种方法来随机抽样所有排列的固定长度子集 import itertools from random import shuffle mylist = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T'] 接近A 下面的方法A存在排列太相似的问题 a_pre = itertools.permutations(mylist,20) a = itertools.islice(a_p

我正在寻找一种方法来随机抽样所有排列的固定长度子集

import itertools
from random import shuffle

mylist = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
接近A 下面的方法A存在排列太相似的问题

a_pre = itertools.permutations(mylist,20)
a = itertools.islice(a_pre,3)

list(a)
['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','p','Q','R','S','T']

['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','p','Q','R','T','S']

['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','p','Q','S','R','T']

方法B 方法B使我更接近我想要的结果,但这里总是存在在列表之间产生相同顺序的风险,所以这种方法是不可行的

#repeat n=3 times

shuffle(mylist)
print(mylist)
[J',B',M',A',O',C',K',S',H',Q',N',T',R',D',G',p',I',E',F',L']

[R',O',C',I',G',E',Q',L',p',J',F',N',A',B',H',T',D',K',M',S']

[L',O',I',G',B',E',R',A',D',N',J',S',H',F',K',M',Q',T',C',p']

但在这里,列表之间总是有产生相同顺序的风险,所以这种方法是不可行的

#repeat n=3 times

shuffle(mylist)
print(mylist)
您可以使用元组(因为列表是不可散列的)和集合(这样就没有重复/相同的列表)来解决这个问题:

from random import shuffle

mylist = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
myset = set()
while len(myset) < 5: #change 5 to however many you want
     shuffle(mylist)
     myset.add(tuple(mylist))
print([list(x) for x in myset])
来自随机导入洗牌
mylist=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
myset=set()
而len(myset)<5:#将5更改为您想要的数量
洗牌(mylist)
添加(元组(mylist))
打印([myset中x的列表(x)])
编辑:正如所指出的:


对于给定的列表,有20个!=2432902008176640000种不同的排列,所以碰撞的可能性非常小


我认为你的问题是,k=N的一个特例 在此基础上,应适用其中所述的两种解决方案。第一个有点慢:)

所以随机抽样(你也暗示了你的问题,只需丢弃重复项…)似乎是目前唯一的答案

这将是非常有趣的,看看是否有一个生成性的解决方案,无论是这个问题,或更普遍的一个。。。 以下是基于该答案的代码:

import itertools
from random import shuffle

mylist = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
n=len(mylist)
k = n
m = 5
samples = set()
tries = 0
while len(samples) < m:
    samples.add(tuple(random.sample(mylist,k)))
    print (len(samples))

print(samples)
print(tries)
导入itertools
从随机导入洗牌
mylist=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T']
n=len(mylist)
k=n
m=5
样本=集合()
尝试=0
而len(样品)
您可以使用它来生成
编号
-th个
N
元素的词典阅读:

def permutation_from_int(N, number):
    '''
    get the number-th lexicographic permutation of length N.

    N: the length of the permutation
    0 <= number <= factorial(N) -1: the number of the desired
    permutation
    '''

    # assert 0 <= number < factorial(N)

    ret = [None] * N
    select = list(range(N))

    for i in range(N - 1, -1, -1):
        index, number = divmod(number, factorial(i))
        element = select[index]
        ret[N - 1 - i] = element
        select.remove(element)
    return ret
请注意,如果测试的数量大于所有排列的空间,则这可能会永远循环

哪些打印(例如):

但正如其他答案中所提到的:如果你有一个20个元素的排列,那么重复排列的机会非常小

考虑一下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))
代码

import string

import more_itertools as mit


iterable = string.ascii_uppercase[:-6]
[random_permutation(iterable) for _ in range(3)]
输出

[('M', 'K', 'Q', 'A', 'I', 'J', 'H', 'T', 'C', 'E', 'P', 'L', 'B', 'N', 'G', 'F', 'S', 'D', 'O', 'R'), 
 ('A', 'G', 'I', 'S', 'E', 'T', 'B', 'Q', 'D', 'M', 'C', 'O', 'J', 'H', 'N', 'F', 'K', 'P', 'R', 'L'), 
 ('C', 'S', 'O', 'H', 'I', 'K', 'A', 'G', 'D', 'B', 'R', 'E', 'L', 'T', 'M', 'N', 'F', 'P', 'Q', 'J')]

是为您提供的第三方库。

您希望生成多少排列?您可以将已使用的列表存储在一个集合中(例如,将列表连接到字符串后,或将其转换为元组后),并避免使用已使用的列表。对于给定列表,有20个!=2432902008176640000个不同的排列,因此碰撞的可能性非常小。可能的重复可能会增加遇到重复的可能性(对于给定列表来说非常非常低)。
[('M', 'K', 'Q', 'A', 'I', 'J', 'H', 'T', 'C', 'E', 'P', 'L', 'B', 'N', 'G', 'F', 'S', 'D', 'O', 'R'), 
 ('A', 'G', 'I', 'S', 'E', 'T', 'B', 'Q', 'D', 'M', 'C', 'O', 'J', 'H', 'N', 'F', 'K', 'P', 'R', 'L'), 
 ('C', 'S', 'O', 'H', 'I', 'K', 'A', 'G', 'D', 'B', 'R', 'E', 'L', 'T', 'M', 'N', 'F', 'P', 'Q', 'J')]