J'ai essayé d'utiliser random.randint(0, 100)
, mais certains chiffres étaient les mêmes. Existe-t-il une méthode / un module pour créer une liste de nombres aléatoires uniques?
Remarque: Le code suivant est basé sur une réponse et a été ajouté après la publication de la réponse. Cela ne fait pas partie de la question; c'est la solution.
def getScores():
# open files to read and write
f1 = open("page.txt", "r");
p1 = open("pgRes.txt", "a");
gScores = [];
bScores = [];
yScores = [];
# run 50 tests of 40 random queries to implement "bootstrapping" method
for i in range(50):
# get 40 random queries from the 50
lines = random.sample(f1.readlines(), 40);
Réponses:
Cela renverra une liste de 10 numéros sélectionnés dans la plage de 0 à 99, sans doublons.
En référence à votre exemple de code spécifique, vous souhaiterez probablement lire toutes les lignes du fichier une fois , puis sélectionner des lignes aléatoires dans la liste enregistrée en mémoire. Par exemple:
De cette façon, vous n'avez besoin de lire le fichier qu'une seule fois, avant votre boucle. Il est beaucoup plus efficace de faire cela que de chercher au début du fichier et de le rappeler
f1.readlines()
à chaque itération de boucle.la source
Vous pouvez utiliser la lecture aléatoire fonction du hasard tel module:
Notez ici que la méthode shuffle ne renvoie aucune liste comme on peut s'y attendre, elle ne fait que mélanger la liste passée par référence.
la source
Vous pouvez d'abord créer une liste de nombres de
a
àb
, oùa
etb
sont respectivement les plus petits et les plus grands nombres de votre liste, puis la mélanger avec l' algorithme de Fisher-Yates ou en utilisant larandom.shuffle
méthode de Python .la source
La solution présentée dans cette réponse fonctionne, mais elle pourrait devenir problématique avec la mémoire si la taille de l'échantillon est petite, mais la population est énorme (par exemple
random.sample(insanelyLargeNumber, 10)
).Pour résoudre ce problème, j'irais avec ceci:
la source
random.sample
Utilise maintenant cette approche pour un petit nombre d'échantillons provenant d'une grande population, donc ce problème de mémoire n'existe plus vraiment. Bien qu'au moment où cette réponse a été rédigée, la mise en œuvre derandom.shuffle
peut avoir été différente.Générateur de nombres pseudo-aléatoires congruentiels linéaires
Ce problème peut être résolu avec un simple générateur congruentiel linéaire . Cela nécessite une surcharge de mémoire constante (8 entiers) et au plus 2 * (longueur de séquence) calculs.
Toutes les autres solutions utilisent plus de mémoire et plus de calcul! Si vous n'avez besoin que de quelques séquences aléatoires, cette méthode sera nettement moins chère. Pour les plages de taille
N
, si vous souhaitez générer de l'ordre de séquencesN
uniquesk
ou plus, je recommande la solution acceptée en utilisant les méthodes intégréesrandom.sample(range(N),k)
car elle a été optimisée en python pour la vitesse.Code
Usage
L'utilisation de cette fonction "random_range" est la même que pour n'importe quel générateur (comme "range"). Un exemple:
Exemples de résultats
la source
prime
, la fonction ne me renverra que 4 réponses possibles, carvalue
c'est la seule chose choisie au hasard avec 4 valeurs possibles, lorsque nous avons besoin d'au moins (4 en choisir 2) = 6, (permettant un ordre non aléatoire).random_range(2,4)
renverra les valeurs {(1, 0), (3, 2), (2, 1), (0, 3)}, mais jamais la paire (3,1) (ou (1,3)). Attendez-vous de nouveaux grands nombres premiers générés aléatoirement à chaque appel de fonction?random_range(v)
retourne àv
des séquences uniques au lieu dev!
)Si la liste de N nombres de 1 à N est générée aléatoirement, alors oui, il y a une possibilité que certains nombres puissent être répétés.
Si vous voulez une liste de nombres de 1 à N dans un ordre aléatoire, remplissez un tableau avec des entiers de 1 à N, puis utilisez un mélange Fisher-Yates ou Python
random.shuffle()
.la source
Si vous devez échantillonner des nombres extrêmement grands, vous ne pouvez pas utiliser
range
car il jette:
De plus, si
random.sample
vous ne pouvez pas produire le nombre d'articles que vous souhaitez en raison de la plage trop petiteil jette:
Cette fonction résout les deux problèmes:
Utilisation avec des nombres extrêmement grands:
Exemple de résultat:
Utilisation où la plage est inférieure au nombre d'éléments demandés:
Exemple de résultat:
Il fonctionne également avec des plages et des étapes négatives:
Exemples de résultats:
la source
Vous pouvez utiliser la bibliothèque Numpy pour une réponse rapide comme indiqué ci-dessous -
L'extrait de code donné répertorie 6 numéros uniques compris entre 0 et 5. Vous pouvez ajuster les paramètres pour votre confort.
Production
Il ne met aucune contrainte comme nous le voyons dans random.sample comme indiqué ici .
J'espère que ça aide un peu.
la source
La réponse fournie ici fonctionne très bien en ce qui concerne le temps ainsi que la mémoire mais un peu plus compliquée car elle utilise des constructions python avancées telles que yield. La réponse la plus simple fonctionne bien dans la pratique, mais le problème avec cette réponse est qu'elle peut générer de nombreux entiers faux avant de construire réellement l'ensemble requis. Essayez-le avec populationSize = 1000, sampleSize = 999. En théorie, il y a une chance qu'il ne se termine pas.
La réponse ci-dessous aborde les deux problèmes, car elle est déterministe et quelque peu efficace bien qu'elle ne soit actuellement pas aussi efficace que les deux autres.
où les fonctions getElem, percolateUp sont telles que définies ci-dessous
Enfin, le timing en moyenne était d'environ 15ms pour une grande valeur de n comme indiqué ci-dessous,
la source
random.randint
fonction 3996 fois, tandis que l'autre cca. 6000 fois. Pas une si grande amélioration, hein?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éfinie ci-dessous,L'idée de base est de garder une trace des intervalles
intervalLst
pour les valeurs possibles à partir desquelles sélectionner nos éléments requis. Ceci est déterministe dans le sens où nous sommes assurés de générer un échantillon en un nombre fixe d'étapes (dépendant uniquement depopulationSize
etsampleSize
).Pour utiliser la fonction ci-dessus pour générer notre liste requise,
On peut aussi comparer avec une solution antérieure (pour une valeur inférieure de populationSize)
Notez que j'ai réduit la
populationSize
valeur car cela produit une erreur de mémoire pour des valeurs plus élevées lors de l'utilisation de larandom.sample
solution (également mentionné dans les réponses précédentes ici et ici ). Pour les valeurs ci-dessus, nous pouvons également observer queextractSamples
surpasse l'random.sample
approche.PS: Bien que l'approche de base soit similaire à ma réponse précédente , il y a des modifications substantielles dans la mise en œuvre ainsi que l'approche avec une amélioration de la clarté.
la source
Une fonction très simple qui résout également votre problème
la source
Le problème avec les approches basées sur les ensembles ("si une valeur aléatoire dans les valeurs de retour, essayez à nouveau") est que leur durée d'exécution est indéterminée en raison de collisions (qui nécessitent une autre itération "réessayer"), en particulier lorsqu'une grande quantité de valeurs aléatoires est renvoyée de la gamme.
Une alternative qui n'est pas sujette à ce runtime non déterministe est la suivante:
la source
la source
Si vous souhaitez vous assurer que les numéros ajoutés sont uniques, vous pouvez utiliser un objet Set
si vous utilisez 2.7 ou supérieur, ou importez le module sets sinon.
Comme d'autres l'ont mentionné, cela signifie que les nombres ne sont pas vraiment aléatoires.
la source
pour échantillonner des entiers sans remplacement entre
minval
etmaxval
:avec jax:
la source
n_samples
d'entre eux? Quel est votre raisonnement derrière cette approche? Pouvez-vous expliquer quels sont les avantages de votre approche par rapport à l'un des nombreux réponses existantes (la plupart datant d'il y a 8 ans)?random.shuffle
, utilisent Mersenne Twister, qui est beaucoup plus lente que les algos proposés par numpy (et probablement jax). numpy et jax permettent d'autres algorithmes de génération de nombres aléatoires. jax permet également la compilation et la différenciation jit, ce qui peut être utile pour la différenciation stochastique. aussi, en ce qui concerne un tableau "peut-être grand", certaines réponses les plus votées font exactement la même chose avecrandom.shuffle
, ce que je ne pense pas être un péché dans un sens relatif ou même absolurandom.shuffle
utilise Mersenne Twister» - c'est le mélange Fisher-Yates, comme mentionné dans plusieurs réponses. Il a une complexité temporelle linéaire, il ne peut donc pas être asymptotiquement plus lent que les algorithmes proposés par toute autre bibliothèque, numpy ou autre. Si numpy est plus rapide, c'est uniquement parce qu'il est implémenté en C, mais cela ne justifie pas de générer une énorme permutation (une qui pourrait même ne pas tenir en mémoire), seulement pour en choisir quelques éléments. Il n'y a pas une seule réponse en dehors de la vôtre qui fasse cela.random
module est écrit en Python, vous pouvez donc facilement voir sa source (essayezrandom.__file__
).À partir de la CLI dans win xp:
Au Canada, nous avons le 6/49 Lotto. J'emballe juste le code ci-dessus dans lotto.bat et exécute
C:\home\lotto.bat
ou justeC:\home\lotto
.Parce que
random.randint
répète souvent un nombre, je l'utiliseset
avecrange(7)
, puis je le raccourcis à une longueur de 6.Parfois, si un nombre se répète plus de 2 fois, la longueur de la liste résultante sera inférieure à 6.
EDIT: Cependant,
random.sample(range(6,49),6)
c'est la bonne voie à suivre.la source
la source
print len(result), len(set(result))
. Vous vous attendriez à voir queresult
cela aurait des éléments uniques une seule fois à chaque1.0851831788708547256608362340568947172111832359638926... × 10^20
essai.