Die Implementierung als Generator macht es sehr angenehm, damit zu arbeiten. Beachten Sie, dass sich diese Implementierung von denen unterscheidet, bei denen das gesamte Eingabearray zuerst gemischt werden muss.
Diese sample
Funktion arbeitet träge, Sie Zufallsgenerator pro Iteration Aufgeben zu N
Elemente, die Sie wünschen. Das ist nett, denn wenn Sie nur Elemente aus einer Liste von möchten, müssen Sie nicht alle 1000 Elemente zuerst berühren.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let ys = xs.slice(0);
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield ys.splice(i,1)[0];
n--; len--;
}
}
// example inputs
let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// get 3 random items
for (let i of sample(3) (items))
console.log(i); // f g c
// partial application
const lotto = sample(3);
for (let i of lotto(numbers))
console.log(i); // 3 8 7
// shuffle an array
const shuffle = xs => Array.from(sample (Infinity) (xs))
console.log(shuffle(items)) // [b c g f d e a]
Ich wählte sample
in einer Art und Weise zu implementieren, die nicht die Eingabearray nicht mutieren, aber man könnte argumentieren, dass eine leicht mutierte Umsetzung günstig ist.
Zum Beispiel könnte die Funktion shuffle
das ursprüngliche Eingabearray mutieren. Oder Sie möchten zu verschiedenen Zeiten von derselben Eingabe abtasten und die Eingabe jedes Mal aktualisieren.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield xs.splice(i,1)[0];
n--; len--;
}
}
// deal :: [Card] -> [Card]
const deal = xs => Array.from(sample (2) (xs));
// setup a deck of cards (13 in this case)
// cards :: [Card]
let cards = 'A234567890JQK'.split('');
// deal 6 players 2 cards each
// players :: [[Card]]
let players = Array.from(Array(6), $=> deal(cards))
console.log(players);
// [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A]
// `cards` has been mutated. only 1 card remains in the deck
console.log(cards);
// [3]
sample
ist nicht mehr ein reine Funktion, weil die Eingangs Mutation Array, aber unter bestimmten Umständen (demonstrierten oben) könnte es mehr Sinn machen.
Ein weiterer Grund, warum ich einen Generator anstelle einer Funktion gewählt, die nur ein Array zurückgibt, weil Sie Sampling bis einige bestimmte Bedingung fortsetzen möchten.
Vielleicht möchte ich die erste Primzahl aus einer Liste von 1.000.000 Zufallszahlen.
- "Wie viele soll ich probieren?" - Sie müssen nicht angeben
- "Muss ich zuerst alle Primzahlen finden und dann eine zufällige Primzahl auswählen?" - Nein.
Weil wir mit einem Generator arbeiten, ist diese Aufgabe trivial
const randomPrimeNumber = listOfNumbers => {
for (let x of sample(Infinity) (listOfNumbers)) {
if (isPrime(x))
return x;
}
return NaN;
}
Dies wird zu einer Zeit kontinuierlich 1 Zufallszahl abzutasten, x
, überprüfen, ob es Primes, dann x
zurück, wenn es . Wenn die Liste der Nummern erschöpft ist, bevor eine Primzahl gefunden wurde, wird NaN
zurückgegeben.
das Array mischen, Pop sie dann weg –
, wie viele Elemente Sie zurückgegeben werden soll? –
Dies wurde schon oft in allen Variationen gefragt. Https://www.google.com/search?q=unique+random+values+array+javascript+site:stackoverflow.com – trincot