Sélection d'un élément au hasard dans un ensemble
Comment puis-je récupérer un élément au hasard dans un jeu?
Je suis particulièrement intéressé par la sélection d'un élément aléatoire à partir d'un
HashSet ou un LinkedHashSet, en Java.
Des Solutions pour d'autres langues sont également les bienvenus.
- Vous devez indiquer certaines conditions pour voir si c'est vraiment ce que vous voulez. - Combien de fois allez-vous être la sélection d'un élément aléatoire? - Les données doivent être stockées dans un HashSet ou LinkedHashSet, ne le sont pas au hasard accessible. - De hachage est la grand (e)? Sont les clés de la petite?
Vous devez vous connecter pour publier un commentaire.
Un peu liés Saviez-Vous:
Il y a des méthodes utiles dans
java.util.Collections
pour traînant les collections:Collections.shuffle(List<?>)
etCollections.shuffle(List<?> liste Aléatoire rnd)
.List
interface, pas laSet
interface discuté par les OP.Solution rapide pour Java à l'aide d'un
ArrayList
et unHashMap
: [element -> index].Motivation: j'avais besoin d'un ensemble d'éléments avec
RandomAccess
propriétés, en particulier pour choisir un élément aléatoire dans l'ensemble (voirpollRandom
méthode). Hasard de la navigation dans un arbre binaire n'est pas exact: les arbres ne sont pas parfaitement équilibré, ce qui ne conduirait pas à une distribution uniforme.Concurrent
sont vraiment à l'abri, ceux enveloppé avecCollections.synchronized()
sont semi-coffre-fort. Aussi, l'OP n'a rien dit à propos de la simultanéité c'est donc valide, et de la bonne réponse.dta
(cela peut être réalisé via la goyave estIterators.unmodifiableIterator
par exemple). Sinon, les implémentations par défaut, par exemple, de removeAll et retainAll dans AbstractSet et de ses parents qui itérateur gâchera votreRandomSet
!C'est plus rapide que la boucle for-each dans l'acceptation réponse:
Pour chaque construction appels
Iterator.hasNext()
sur chaque boucle, mais depuisindex < set.size()
, cette vérification est inutile de frais généraux. J'ai vu un de 10 à 20% de boost en vitesse, mais YMMV. (Aussi, cette compile sans avoir à ajouter une instruction de retour.)Notez que ce code (et la plupart des autres réponses) peuvent être appliquées à n'importe quelle Collection, et pas seulement Ensemble. Au générique de la méthode de la forme:
Si vous voulez le faire en Java, vous devez envisager de copier les éléments dans une sorte de random-access collection (comme une liste de tableaux). Car, à moins que votre jeu est petit, l'accès à l'élément sélectionné sera cher (O(n) au lieu de O(1)). [ed: liste de copie est également en O(n)]
Sinon, vous pourriez regarder pour un autre Jeu de mise en œuvre qui correspond le mieux à vos exigences. Le ListOrderedSet de Communes des Collections de l'air prometteur.
En Java:
Clojure solution:
nth
élément vous devez parcourir laseq
ainsi.Perl 5
Ici est une façon de le faire.
C++. Cela devrait être assez rapide, car il ne nécessite pas d'itération sur l'ensemble, ou le tri. Cela devrait fonctionner hors de la boîte avec la plupart les compilateurs modernes, en supposant qu'ils soutiennent tr1. Si non, vous devrez peut-être utiliser Boost.
La Boost docs sont utiles ici pour expliquer cela, même si vous n'utilisez pas de coup de pouce.
L'astuce consiste à utiliser le fait que les données ont été divisées en segments, et d'identifier rapidement un choisi au hasard seau (avec la probabilité).
Solution ci-dessus parlent en termes de temps de latence, mais ne garantit pas une probabilité égale de chaque index sélectionné.
Si cela doit être considéré, essayez réservoir d'échantillonnage. http://en.wikipedia.org/wiki/Reservoir_sampling.
Les Collections.shuffle() (comme suggéré par quelques-uns) utilise un algorithme de ce type.
Puisque vous avez dit "des Solutions pour d'autres langues sont également les bienvenus", voici la version pour Python:
Tu ne peux pas obtenir la taille/longueur de la série/tableau, générer un nombre aléatoire entre 0 et la taille/longueur, puis d'appeler l'élément dont l'index correspond à ce nombre? HashSet a un .méthode size (), je suis assez sûr.
Dans psuedocode -
PHP, en supposant que "set" est un tableau:
Le Mersenne Twister fonctions sont mieux, mais il n'y a pas de MT équivalent de array_rand en PHP.
Icône a un type de jeu et un random-élément opérateur unaire "?", donc l'expression
va produire un nombre aléatoire entre 1 et 5.
La graine aléatoire est initialisé à 0 lorsqu'un programme est exécuté, de sorte à produire des résultats différents à chaque exécution, l'utilisation
randomize()
En C#
Javascript solution 😉
Ou alternativement:
En lisp
ELT
il pourrait fonctionner pour n'importe quelle séquence.Dans Mathematica:
Ou, dans les versions récentes, il suffit de:
Ce reçu un vote, peut-être parce qu'il manque d'explication, ici, on est à:
Random[]
génère un pseudo flotter entre 0 et 1. Ce nombre est multiplié par la longueur de la liste et puis le plafond de la fonction est utilisée pour arrondir à l'entier suivant. Cet indice est ensuite extrait à partir dea
.Depuis la table de hachage de la fonctionnalité est souvent le cas avec les règles en Mathematica, et les règles sont stockées dans des listes, on peut utiliser:
Que diriez-vous simplement
C'est identique à accepté de répondre (Khoth), mais avec les inutiles
size
eti
variables supprimées.Si faire l'écart avec les deux variables mentionnées ci-dessus, la solution ci-dessus reste aléatoire, car nous sommes fier au hasard (à partir de un choisi au hasard index) pour décrémenter lui-même vers
0
à chaque itération.Malheureusement, cela ne peut être fait de manière efficace (mieux que O(n)) dans la Bibliothèque Standard de définir des conteneurs.
C'est étrange, car il est très facile d'ajouter une étude randomisée de sélection de la fonction de hachage établit ainsi que les binaires ensembles. Dans un pas à la faible densité de hachage ensemble, vous pouvez essayer de participants au hasard, jusqu'à ce que vous obtenez un hit. Pour un arbre binaire, vous pouvez choisir au hasard entre les à gauche ou à droite de la sous-arborescence, avec un maximum de O(log2) étapes. J'ai mis en place une démo de la suite ci-dessous:
J'ai eu [995, 975, 971, 995, 1057, 1004, 966, 1052, 984, 1001] en sortie, de sorte que la distribution des coutures bonne.
J'ai lutté avec le même problème pour moi, et je n'ai pas encore décidé de la météo le gain de performance de ce plus efficace pick vaut la surcharge de l'aide d'un python en fonction de la collection. Je pourrais bien sûr, de l'affiner et de le traduire à C, mais c'est trop de travail pour moi aujourd'hui 🙂
Dans Java 8:
PHP, à l'aide de MT:
Pour le fun, j'ai écrit un RandomHashSet repose sur le rejet de l'échantillonnage. C'est un peu hacky, depuis HashMap ne nous laisse pas accéder à la table directement, mais il devrait fonctionner très bien.
Il ne pas utiliser toute la mémoire supplémentaire, et la recherche en temps est O(1) amorti. (Parce que java table de hachage est dense).
vous pouvez également transférer l'ensemble de la matrice de l'utilisation de la matrice de
il va probablement travailler sur petite échelle, je vois pour la boucle dans le plus voté réponse est O(n) de toute façon
Si vraiment vous voulez juste de choisir "tout" objet à partir de la
Set
, sans aucune garantie sur le caractère aléatoire, le plus simple est de prendre le premier est retourné par l'itérateur.Le plus facile avec Java 8 est:
où
n
est un nombre entier aléatoire. Bien sûr, il est de moins en moins de performances qu'avec lafor(elem: Col)
Une solution générique à l'aide de Khoth de répondre en tant que point de départ.
Si la taille de l'ensemble n'est pas grand, puis à l'aide de Matrices, ce qui peut être fait.
Avec Goyave nous pouvons faire un peu mieux que Khoth réponse:
Si vous n'avez pas l'esprit d'un 3ème partie de la bibliothèque, le Utils la bibliothèque dispose d'un IterableUtils qui a un randomFrom(Itérable objet iterable) méthode qui vous permettra de prendre un Jeu et le retour d'un élément au hasard dans il
Il est dans le Dépôt Central de Maven à:
après la lecture de ce thread, le meilleur que j'ai pu écrire c'est:
Random
à l'heure actuelle;new Random()
retourne correctement graines instance de la boîte.