Afin d'obtenir un programme qui génère une liste de valeurs aléatoires sans doublons, qui soit déterministe, efficace et construit avec des constructions de programmation de base, considérez la fonction extractSamples
définis ci-dessous,
def extractSamples(populationSize, sampleSize, intervalLst) :
import random
if (sampleSize > populationSize) :
raise ValueError("sampleSize = "+str(sampleSize) +" > populationSize (= " + str(populationSize) + ")")
samples = []
while (len(samples) < sampleSize) :
i = random.randint(0, (len(intervalLst)-1))
(a,b) = intervalLst[i]
sample = random.randint(a,b)
if (a==b) :
intervalLst.pop(i)
elif (a == sample) : # shorten beginning of interval
intervalLst[i] = (sample+1, b)
elif ( sample == b) : # shorten interval end
intervalLst[i] = (a, sample - 1)
else :
intervalLst[i] = (a, sample - 1)
intervalLst.append((sample+1, b))
samples.append(sample)
return samples
L'idée de base est de garder une trace des intervalles intervalLst
pour les valeurs possibles parmi lesquelles nous pouvons sélectionner les éléments requis. Il s'agit d'un processus déterministe dans le sens où nous avons la garantie de générer un échantillon en un nombre fixe d'étapes (qui dépend uniquement de la valeur de l'échantillon). populationSize
y sampleSize
).
Pour utiliser la fonction ci-dessus afin de générer notre liste requise,
In [3]: populationSize, sampleSize = 10**17, 10**5
In [4]: %time lst1 = extractSamples(populationSize, sampleSize, [(0, populationSize-1)])
CPU times: user 289 ms, sys: 9.96 ms, total: 299 ms
Wall time: 293 ms
Nous pouvons également comparer avec une solution antérieure (pour une valeur inférieure de populationSize)
In [5]: populationSize, sampleSize = 10**8, 10**5
In [6]: %time lst = random.sample(range(populationSize), sampleSize)
CPU times: user 1.89 s, sys: 299 ms, total: 2.19 s
Wall time: 2.18 s
In [7]: %time lst1 = extractSamples(populationSize, sampleSize, [(0, populationSize-1)])
CPU times: user 449 ms, sys: 8.92 ms, total: 458 ms
Wall time: 442 ms
Notez que j'ai réduit populationSize
car il produit une erreur de mémoire pour les valeurs plus élevées lors de l'utilisation de l'outil de gestion de la mémoire. random.sample
solution (également mentionnée dans les réponses précédentes aquí y aquí ). Pour les valeurs ci-dessus, nous pouvons également observer que extractSamples
surpasse le random.sample
approche.
P.S. : Bien que l'approche de base soit similaire à celle de ma réponse précédente Les modifications apportées à la mise en œuvre et à l'approche, ainsi que l'amélioration de la clarté, sont substantielles.
2 votes
S'ils sont uniques, ils peuvent être véritablement aléatoires dans le bon contexte. Comme un échantillon aléatoire d'index sans remplacement peut encore être complètement aléatoire.