Frage

Bitte einen einfachste Weg vorschlagen, eine zufällige Shuffled Sammlung von count ‚n‘ aus einer Sammlung mit ‚N‘ Elementen zu erhalten. wobei n <= N

War es hilfreich?

Lösung

Eine weitere Option ist SortiertNach zu verwenden und auf einem GUID-Wert zu sortieren, die Sie tun können, so verwenden:

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

Ich habe einige empirische Versuche, mich zu überzeugen, dass die oben erzeugt tatsächlich eine zufällige Verteilung (die es zu tun scheint). Sie können meine Ergebnisse unter Techniken für Randomly Neuordnen ein Array .

Andere Tipps

Im Anschluss an mquander Antwort und Dan Blanchard Kommentar, hier ist eine LINQ freundliche Erweiterung Methode, die ein Fisher-Yates-Durstenfeld mischt :

// 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];
        }
    }
}

Dieses einige Probleme mit „random bias“ hat, und ich bin sicher, dass es nicht optimal ist, ist dies eine weitere Möglichkeit:

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

Shuffle die Sammlung in zufälliger Reihenfolge und die erste n Elemente aus dem Ergebnis.

Ein bisschen weniger zufällig, aber effizient:

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);

Ich schreibe dies überschreibt Methode:

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>();
        }

Dann habe ich meine Quellenliste (alle Artikel)

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

Schließlich nenne ich „Randomize“ und ich bekomme eine zufällige Unter Sammlung von Gegenständen, in meinem Fall 5 Artikel:

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

Es tut uns hässlich Code :-), aber


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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top