Question

Veuillez suggérer le moyen le plus simple d’obtenir une collection aléatoire de comtes 'n' à partir d’une collection contenant des éléments 'N'. où n < = N

Était-ce utile?

La solution

Une autre option consiste à utiliser OrderBy et à trier sur une valeur GUID, que vous pouvez utiliser à l'aide de:

var result = sequence.OrderBy(elem => Guid.NewGuid());

J'ai fait quelques tests empiriques pour me convaincre que ce qui précède génère effectivement une distribution aléatoire (ce qui semble être le cas). Vous pouvez voir mes résultats sur les Techniques de réorganisation aléatoire d'un groupe .

Autres conseils

En complément de la réponse de mquander et du commentaire de Dan Blanchard, voici une méthode d’extension compatible avec LINQ qui exécute un Mélange Fisher-Yates-Durstenfeld :

// take n random items from yourCollection
var randomItems = yourCollection.Shuffle().Take(n);

// ...

public static class EnumerableExtensions
{
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
    {
        return source.Shuffle(new Random());
    }

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (rng == null) throw new ArgumentNullException("rng");

        return source.ShuffleIterator(rng);
    }

    private static IEnumerable<T> ShuffleIterator<T>(
        this IEnumerable<T> source, Random rng)
    {
        var buffer = source.ToList();
        for (int i = 0; i < buffer.Count; i++)
        {
            int j = rng.Next(i, buffer.Count);
            yield return buffer[j];

            buffer[j] = buffer[i];
        }
    }
}

Cela a quelques problèmes avec " biais aléatoire " et je suis sûr que ce n'est pas optimal, c'est une autre possibilité:

var r = new Random();
l.OrderBy(x => r.NextDouble()).Take(n);

Mélangez la collection dans un ordre aléatoire et prenez la première < code> n éléments du résultat.

Un peu moins aléatoire, mais efficace:

var rnd = new Random();
var toSkip = list.Count()-n;

if (toSkip > 0)
    toSkip = rnd.Next(toSkip);
else
    toSkip=0;

var randomlySelectedSequence = list.Skip(toSkip).Take(n);

J'écris cette méthode de substitution:

public static IEnumerable<T> Randomize<T>(this IEnumerable<T> items) where T : class
{
     int max = items.Count();
     var secuencia = Enumerable.Range(1, max).OrderBy(n => n * n * (new Random()).Next());

     return ListOrder<T>(items, secuencia.ToArray());
}

private static IEnumerable<T> ListOrder<T>(IEnumerable<T> items, int[] secuencia) where T : class
        {
            List<T> newList = new List<T>();
            int count = 0;
            foreach (var seed in count > 0 ? secuencia.Skip(1) : secuencia.Skip(0))
            {
                newList.Add(items.ElementAt(seed - 1));
                count++;
            }
            return newList.AsEnumerable<T>();
        }

Ensuite, j'ai ma liste de sources (tous les éléments)

var listSource = p.Session.QueryOver<Listado>(() => pl)
                        .Where(...);

Enfin, j’appelle " Randomize " et je reçois une sous-collection d'objets au hasard, dans mon cas, 5 articles:

var SubCollection = Randomize(listSource.List()).Take(5).ToList();

Désolé pour le code laid :-), mais


var result =yourCollection.OrderBy(p => (p.GetHashCode().ToString() + Guid.NewGuid().ToString()).GetHashCode()).Take(n);

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top