Optimale requête LINQ pour obtenir aléatoires de la sous-collection - Shuffle
S'il vous plaît suggérer une façon la plus simple d'obtenir un aléatoire mélangées collection du comte 'n' à partir d'une collection ayant N éléments. où n <= N
Vous devez vous connecter pour publier un commentaire.
Une autre option est d'utiliser OrderBy et de trier sur un GUID de la valeur, vous pouvez le faire en utilisant:
J'ai fait quelques tests empiriques pour me convaincre moi-même que ci-dessus génère une distribution aléatoire (ce qui semble le faire). Vous pouvez voir mes résultats à Les Techniques au Hasard et la Réorganisation d'un Tableau.
Plus de mquander la réponse de Dan Blanchard commentaire, voici une LINQ-amicale de la méthode d'extension qui effectue un De Fisher-Yates-Durstenfeld shuffle:
seq.Shuffle().ElementAt(n)
plusieurs fois, puis, vous êtes re-brassage à chaque fois, donc il est probable que vous aurez un autre élément à la positionn
. Si vous voulez shuffle après ensuite, vous avez besoin de stocker la séquence en béton collection d'un certain type: par exemple,var list = seq.Shuffle().ToList()
. Ensuite, vous pouvez fairelist.ElementAt(n)
aussi souvent que vous le souhaitez, ou simplementlist[n]
-- et vous obtiendrez toujours le même élément..ShuffleIterator()
au lieu de mettre ce code dans.Shuffle()
? Et puisque vous appelez.ToList()
, n'est-ce pas à la parcourir l'ensemble de la collection plutôt que de simplement le montant demandé par.Take(n)
? J'ai l'intuition que la première question peut répondre à ma deuxième question.myList.ElementAt(0)
. Je reçois une autre chaîne chaque fois que j'appellestring.Join(",", myList)
.Shuffle
méthodes retournent un paresseuxIEnumerable<T>
qui sera réévalué chaque fois que vous l'utilisez dans unstring.Join
ouElementAt
appel. C'est juste la nature deIEnumerable<T>
; si vous voulez le comportement d'un béton de la collection, alors vous devriez vraiment créer un béton collection en appelantToArray
ouToList
sur le résultat de laShuffle
appel..Shuffle()
thread-safe? Je ne vois pas pourquoi il ne devrait pas être, mais j'obtiens des résultats étranges... plusieurs threads semblent tirer la même shuffle résultats.Ce qui a quelques problèmes avec "random biais" et je suis sûr que c'est pas optimal, c'est une autre possibilité:
Random
lui-même. Il est également très efficace.Shuffle la collection dans un ordre aléatoire et prendre la première
n
les éléments de la suite.Un peu moins aléatoire, mais efficace:
J'écris ceci remplace la méthode:
Puis, j'ai ma liste de source (tous les articles)
Enfin, je l'appelle "Aléatoire" et je suis aléatoires de la sous-collection d'éléments, dans mon cas, 5 éléments:
newList
. Peut-être envisager d'utiliseryield return
à l'intérieur de laforeach
déclaration.Enumerable.Range(1, max).OrderBy(n => n * n * (new Random()).Next())
est terrible - c'est pas aléatoire du tout. l'appel denew Random()).Next()
comme ça va juste retourner le même nombre dans la plupart des cas et lan * n
fait le nombre biaisée - et, éventuellement, pourrait provoquer un débordement des exceptions.Désolé pour les vilaines code :-), mais
p.GetHashCode().ToString() + Guid.NewGuid().ToString()).GetHashCode()
n'est pas aléatoire. Il peut paraître aléatoire, mais il ne l'est pas. Vous devez utiliser un générateur de nombres aléatoires pour l'aléatoire de données, les scientifiques ont conçu spécifiquement pour être aussi aléatoire que possible.