Module de Python 'Random' a une fonction aléatoire.choice code>
aléatoire.choice (SEQ) code> strong>
Renvoie un élément aléatoire de la séquence non vide SEQ. SiSEQ code> est vide, augmenteindexerror code>. P> blockQuote>Comment puis-je imiter cela dans .net ?net? P>
public T RandomChoice<T> (IEnumerable<T> source)
- 'La séquence est trop longue pour économiser à la mémoire' li>
- 'Vous ne pouvez faire que boucle sur la séquence une fois " li>
- 'La séquence n'a pas de méthode de longueur / dénombrement' (Ã La .NET iEnumerable) li> ul> p>
7 Réponses :
Eh bien, obtenez une liste de tous les éléments de la séquence. Demandez à un générateur de nombres aléatoires pour l'index, renvoyer Elemnt par index. Définissez quelle séquence est - iEnumerable serait la plus évidente, mais vous devez matérialiser cela dans une liste alors de connaître le nombre d'éléments pour le générateur de nombres aléatoires. C'est BTW., Pas imiter, il est implémenter. P>
est-ce une question de cours d'étude débutant de devoirs? p>
private static Random rng = new Random(); ... return source.Skip(rng.next(source.Count())).Take(1);
1) N'oubliez pas le verrouillage. 2) Votre code nécessite plusieurs énumérations d'une séquence, qui devrait généralement être évitée. 3) prendre (1) code> renvoie une séquence d'éléments unique. Vous devez utiliser premier () code> à la place.
Pour éviter d'itération à travers la séquence deux fois (une fois pour le compte et une fois pour l'élément), il est probablement une bonne idée de sauvegarder votre séquence dans un tableau avant d'obtenir son élément aléatoire:
public static class RandomExt {
private static Random rnd = new Random();
public static T RandomChoice<T> (this IEnumerable<T> source) {
var arr = source.ToArray();
return arr[rnd.Next(arr.Length)];
}
public static T RandomChoice<T> (this ICollection<T> source) {
return source[rnd.Next(rnd.Count)];
}
}
J'aime particulièrement cela comme une méthode d'extension. +1
Pourquoi ilist icollection
Cela viole la contrainte 'La séquence est trop longue pour économiser en mémoire' si je remarque que vous avez probablement répondu avant que la contrainte ait été ajoutée ...
@Amitmittal Cette contrainte n'était pas là quand j'ai répondu à la question.
ahh ... juste quand je montageais le commentaire après avoir remarqué que :)
@dasblinkenlight, @codeinchaos: J'ai dit IList code> car icollection code> n'a pas l'indexer [index] code> Notation. Donc, votre code édité ne compilera plus. : P
public static T RandomChoice<T> (this IEnumerable<T> source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
var list = source.ToList();
if (list.Count < 1)
{
throw new MissingMemberException();
}
var rnd = new Random();
return list[rnd.Next(0, list.Count)];
}
J'irais avec La réponse de Dasblinkenlight , avec un petit changement: Tirer parti du fait que Notez que j'ai également modifié l'interface de la réponse susmentionnée Pour que cela soit plus cohérent avec la version Python que vous avez référencée dans votre question: p> edit strong>: j'aime source code> peut déjà être une collection indexée, auquel cas vous n'avez vraiment pas besoin de remplir un nouveau tableau (ou une nouvelle liste):
Pour créer une méthode qui compte uniquement la source une seule fois et ne doit pas allouer la mémoire pour la stocker temporairement, vous comptez le nombre d'éléments que vous avez itératés et déterminer la probabilité que l'élément actuel soit le résultat: < Pré> xxx pré>
Lorsque vous êtes au premier élément, la probabilité est 1/1 qu'elle doit être utilisée (comme c'est le seul élément que vous avez vu aussi loin). Lorsque vous êtes au second élément, la probabilité est de 1/2 qu'il devrait remplacer le premier élément, et ainsi de suite. P>
Ceci utilisera naturellement un peu plus de processeur, car il crée un hasard Nombre par article, pas seulement un seul nombre aléatoire pour sélectionner un élément, car Dasblinkenlight a souligné. Vous pouvez vérifier si la source implémente Remarque: vous devez envisager d'envoyer l'instance code> aléatoire code> dans la méthode. Sinon, vous obtiendrez la même graine aléatoire si vous appelez la méthode deux fois trop près du temps, car la graine est créée à partir de l'heure actuelle. P> résultat d'un test, cueillette un chiffre À partir d'un tableau contenant 0 - 9, 1000000 fois, pour montrer que la distribution des numéros choisis n'est pas asymétrique: p> ilist
Ah, gentil. Je me souviens de devoir faire quelque chose comme ça une fois! La chose est, je pense que vous devrez montrer aux mathématiques pour convaincre tous les lecteurs que c'est correct (ce n'est pas immédiatement intuitif que c'est correct-au moins pour moi).
Je suggérerais également d'optimiser encore pour le cas où source code> est un ilist
+1 très gentil! Voici un Lien vers une simple preuve par induction que cet algorithme choisit un élément aléatoire avec la probabilité de 1/1 code>. Vous voudrez peut-être noter que cet algorithme enregistre la mémoire de la variable TEMP à la charge d'utilisation de CPU supplémentaire pour générer des numéros aléatoires N code> au lieu d'une seule. Peu importe avec le RNG régulier, mais en utilisant une forte cryptographique peut transformer cela en un compromis.
Imo le passage de l'instance de aléatoire code> devrait faire partie de votre code actuel et non seulement une note plusieurs paragraphes ultérieurement.
@dasblinkenlight même des crypto prngs sont assez rapides. Certains sont inférieurs à 8 CPB et même le RNGCryptoServiceService relativement lent est à 40 CPB.
@CODEINCHAOS: Oui, peut-être. Je voulais montrer une méthode qui avait la signature exacte que dans la question.
en supposant que l'on a une méthode d'extension la méthode ienumérable.minby code>: minby code> ne sauvegarder pas la séquence en mémoire, Cela fonctionne comme ienumerable.min code> faisant une itération (voir
Ce n'est pas très différent de ce que @dasblinkenlight a suggéré. Cela implique également de créer un certain nombre de nombres aléatoires, puis de décider quand se terminer (bien que les chèques soient différents dans les deux cas).
Vous dites que vous voulez une fonction qui vous retournerait exactement ce que Python fait i>? Ou vous voulez une fonction avec le même contrat i>? C'est-à-dire que vous seriez heureux si la fonction .NET renvoyait différents éléments de ce que Python serait?
Juste pour commenter les réponses fournies, @Matthickford, vous devriez peut-être envisager, en plus d'un
ienumerable code> include uniList code> surcharge (ou un chèque dans leienumerable code> si c'est unilist code>) afin que vous puissiez éviter d'énumérer et de créer une collection copiée. Edit: Vous pouvez également ajouter unparamètres code> surcharger pour extraire une liste à partir de la compilation:RandomChoice ("pomme", "poire", "orange") code>Aakashm, je demande un analogue .NET de la fonction Python. Qu'est-ce qu'un contrat?
Oh, notre difficulté à communiquer est que les mots anglais «émulent», «analogique» et «contrat» sont surchargés avec des significations techniques précises. J'utilise les définitions de dictionnaire. Et par dictionnaire, je ne veux pas dire la structure de données!