> pick | shuffle | pair <
// Indsæt en liste, træk vindere, bland rækkefølgen eller del folk op i grupper - alt sammen i din browser
Vælg N tilfældige elementer
Træk et vilkårligt antal vindere fra din liste. Uden tilbagelægning for unikke vindere eller med tilbagelægning for trækninger i vægtet stil.
Uvildig Fisher-Yates-blanding
Omarrangerer hele listen med den klassiske Knuth-blanding. Enhver permutation er lige sandsynlig - ingen naive sorteringstricks her.
Del op i grupper
Del en liste op i par, trioer eller en vilkårlig gruppestørrelse. Perfekt til pararbejde, code review-rotationer eller pakkeleg-parringer.
Reproducerbarhed med seed
Angiv en seed-streng for at få en deterministisk trækning. Samme seed plus samme liste giver altid samme resultat - kan deles og verificeres.
// OM DEN TILFÆLDIGE UDVÆLGER
Sådan virker det:
Dette værktøj bruger Fisher-Yates- (også kaldet Knuth-) blandingen: gennemgå arrayet fra sidste indeks til første, og byt ved hvert trin det aktuelle element med ét på et ensartet tilfældigt tidligere indeks. Dette giver en uvildig, ensartet permutation i O(n)-tid. Det naive trick array.sort(() => Math.random() - 0.5) er skævt, fordi JavaScript-sorteringssammenligninger skal være transitive - tilfældige sammenligninger overtræder det og skævvrider fordelingen. Til trækninger uden seed henter vi entropi fra window.crypto.getRandomValues. Når du angiver en seed-streng, hasher vi den med cyrb53 til et 53-bit heltal og driver derefter en mulberry32-PRNG, så identiske seeds giver identiske, reproducerbare resultater.
Algoritme:
for i = n-1 down to 1: j = randInt(0, i); swap(a[i], a[j]) - unbiased Fisher-Yates
Standarder & referencer:
- >Web Crypto API (W3C) - crypto.getRandomValues til kryptografisk stærk tilfældighed
- >Fisher-Yates-blanding (1938), populariseret af Donald Knuth i The Art of Computer Programming bind 2
- >mulberry32 - lille, hurtig, velfordelt seed-PRNG af Tommy Ettinger
- >cyrb53 - 53-bit streng-hash af bryc, brugt til at omdanne en seed-streng til en numerisk PRNG-tilstand
Almindelige anvendelser:
- >Konkurrencer, lodtrækninger og udnævnelse af en tilfældig vinder blandt deltagere
- >Navnetrækninger i klasseværelset og udvælgelse af elever til uventede spørgsmål
- >Sportsholdsparring, partræning og turneringsskemaer
- >Tildeling af code review-anmeldere på tværs af et udviklingsteam
- >Stikprøveudvælgelse til A/B-test og randomiserede undersøgelseskohorter
- >Pakkeleg-par, gaveudvekslinger og frokostmakkere i teamet
- >Tilfældige testinput og fuzzing-seeds til QA
- >Gruppebaseret beslutningstagning og afgørelse af uafgjorte
- >Udvælgelse af skinjury og randomiserede interviewpaneler
- >Lotteri-lignende trækninger til lokale arrangementer og præmier
Relaterede værktøjer:
- >Tilfældig talgenerator — det tekstbaserede modstykke: vælg tal i et interval med de samme seed-reproducerbarhedsprimitiver
- >UUID-generator — tilfældige v4-identifikatorer, når du har brug for et unikt uigennemsigtigt id frem for en vinder fra en liste
- >Adgangskodegenerator — kryptografisk tilfældige strenge med kontrol over tegnsættet til tokens og legitimationsoplysninger
- >randompickerwheel.app — lykkehjuls-grænseflade som supplement til denne tekstudvælger, perfekt til live trækninger foran publikum, spørgsmål i klassen og afsløringer på skærmen
// EKSEMPLER PÅ TRÆKNINGER
Konkurrence — vælg 3 vindere blandt 50 deltagere
> input:
alice@x.com
bob@x.com
carlos@x.com
…(50 linjer i alt)
> config:
Tilstand=Pick N, Antal=3, Tillad dubletter=off, Seed=(tom)
> output:
1. carlos@x.com
2. priya@x.com
3. wei@x.com
Bland en liste med 10 navne til en præsentationsrækkefølge
> input:
Alice
Bob
Charlie
Dana
Evelyn
Farouk
Gabriela
Hiroshi
Isabella
Jamal
> config:
Tilstand=Shuffle, Seed=(tom)
> output:
1. Hiroshi
2. Alice
3. Farouk
4. Jamal
5. Dana
6. Evelyn
7. Bob
8. Isabella
9. Gabriela
10. Charlie
Del en klasse på 12 elever op i grupper på 2
> input:
S01
S02
S03
S04
S05
S06
S07
S08
S09
S10
S11
S12
> config:
Tilstand=Pair Up, Gruppestørrelse=2, Seed=class-2026-05-02
> output:
Gruppe 1: S07, S02
Gruppe 2: S11, S04
Gruppe 3: S09, S12
Gruppe 4: S01, S06
Gruppe 5: S03, S10
Gruppe 6: S08, S05
Reproducerbar trækning med seed — kør to gange med samme seed, få de samme vindere
> input:
alpha
bravo
charlie
delta
echo
foxtrot
golf
hotel
> config:
Tilstand=Pick N, Antal=2, Seed=launch-day, Tillad dubletter=off
> output:
Kørsel 1: 1. echo
2. bravo
Kørsel 2: 1. echo
2. bravo (identisk — med seed)
// HVORFOR NAIVT .SORT() ER SKÆVT
En almindelig one-liner-blanding er arr.sort(() => Math.random() - 0.5). Den ser elegant ud, fylder én linje og føles tilfældig — men den resulterende permutationsfordeling er langtfra ensartet. ECMAScript-specifikationen kræver, at sammenligningsfunktioner er deterministiske og transitive: hvis a < b og b < c, så a < c. En plat-eller-krone-sammenligner overtræder den kontrakt, og motorens sorteringsimplementering besøger sammenligningspar i et ujævnt mønster.
V8 (Chrome, Node) bruger Timsort; ældre motorer brugte quicksort eller mergesort. Hver implementering besøger et forskelligt udsnit af sammenligningspar og genbruger cachelagrede sammenligninger på forskellige måder. Som Mike Bostock påviste empirisk (bost.ocks.org/mike/shuffle/compare.html), giver den naive sortering stærkt skæve resultater, hvor nogle permutationer optræder flere gange oftere end andre — uacceptabelt for en konkurrence, en A/B-bucket eller enhver trækning, der skal være retfærdig.
Den korrekte algoritme er Fisher-Yates (Knuth-blanding): gennemgå arrayet fra sidste indeks ned til første, og byt ved hvert trin det aktuelle element med ét valgt ensartet tilfældigt blandt indeksene 0..i. Den kører i O(n), bruger O(1) ekstra plads og giver beviseligt enhver permutation med lige stor sandsynlighed.
// BAD: NOT uniformly random
const shuffled = arr.sort(() => Math.random() - 0.5);
// GOOD: Fisher-Yates (Knuth) shuffle
function shuffle(arr) {
const a = arr.slice();
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
// IMPLEMENTÉR DET SELV
Vil du bygge din egen udvælger eller efterprøve vores? Dette er præcis de primitiver, denne side bruger — små, uden afhængigheder og identiske med det, der kører i din browser, når du klikker PICK. Kopiér dem direkte ind i et Node-script eller en anden webapp.
// Fisher-Yates shuffle (uniform, O(n))
function shuffle(arr, rng = Math.random) {
const a = arr.slice();
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(rng() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
// Pick N without replacement (shuffle then slice)
function pickN(arr, n, rng = Math.random) {
if (n > arr.length) {
throw new Error('n exceeds list size');
}
return shuffle(arr, rng).slice(0, n);
}
// mulberry32 seeded PRNG + cyrb53 string hash
// cyrb53: turn a seed string into a 53-bit integer
function cyrb53(str, seed = 0) {
let h1 = 0xdeadbeef ^ seed;
let h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < str.length; i++) {
ch = str.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^
Math.imul(h2 ^ (h2 >>> 13), 3266489909);
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^
Math.imul(h1 ^ (h1 >>> 13), 3266489909);
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
}
// mulberry32: tiny seeded PRNG -> [0, 1)
function mulberry32(a) {
return function () {
a |= 0; a = (a + 0x6D2B79F5) | 0;
let t = a;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
// Build a seeded picker:
const h = cyrb53('my-seed', 1);
const state = (h ^ Math.floor(h / 4294967296)) >>> 0;
const rng = mulberry32(state);
const winners = pickN(['alice', 'bob', 'carlos'], 2, rng);
>> ofte stillede spørgsmål
Sp.: Hvordan genereres tilfældigheden?
Sv.: Når der ikke angives nogen seed, bruger vi window.crypto.getRandomValues, browserens kryptografisk sikre tilfældighedsgenerator baseret på Web Crypto API. Det er den samme entropikilde, der bruges til kryptografiske nøgler og tokens, så den er mere end stærk nok til lodtrækninger og blandinger. Når du angiver en seed, udleder vi deterministisk en 53-bit tilstand via cyrb53-streng-hashen og fører den ind i en mulberry32-PRNG, så trækningen er reproducerbar.
Sp.: Kan jeg få det samme resultat to gange ved hjælp af en seed?
Sv.: Ja. Skriv en vilkårlig streng i SEED-feltet - en dato, et konkurrencenavn, en hash, hvad som helst. Den samme seed kombineret med den samme inputliste og den samme tilstand giver altid præcis det samme output. Det er uvurderligt til gennemsigtige konkurrencer, hvor du vil offentliggøre seedet på forhånd og lade deltagerne verificere trækningen, eller til udviklingsrotationer, der skal være reproducerbare på tværs af maskiner.
Sp.: Hvad er forskellen mellem Pick N og Shuffle?
Sv.: Pick N udvælger en delmængde af størrelse N fra din liste, eventuelt med tilbagelægning (dubletter tilladt). Shuffle returnerer hele listen omarrangeret - ingen elementer fjernes eller gentages, blot omordnes. Brug Pick N, når du kun ønsker nogle få vindere blandt mange deltagere; brug Shuffle, når hvert element stadig skal deltage, men i en ny tilfældig rækkefølge, som en præsentationskø eller afspilningsliste.
Sp.: Er array.sort(() => Math.random() - 0.5) faktisk tilfældig?
Sv.: Nej, den er skæv. ECMAScript-specifikationen kræver, at sorteringssammenligninger er deterministiske og transitive (hvis a < b og b < c så a < c). En tilfældig sammenligner overtræder den kontrakt, og forskellige JavaScript-motorer kører forskellige underliggende sorteringsalgoritmer (TimSort, mergesort, quicksort), som interagerer med den tilfældige sammenligner på forskellige måder. Resultatet er en ujævn fordeling, hvor nogle permutationer optræder langt oftere end andre. Fisher-Yates er den korrekte algoritme.
Sp.: Kan jeg danne par af en liste med et ulige antal?
Sv.: Ja. Pair Up-tilstanden blander din liste med Fisher-Yates og opdeler den derefter efter den valgte gruppestørrelse. Hvis totalen ikke går lige op, bliver den sidste gruppe mindre og markeres tydeligt som en restgruppe i outputtet. Ved en ulige liste kan du enten acceptere en solo-indtastning, øge gruppestørrelsen eller tilføje et pladsholdernavn som "bye" inden trækningen.
Sp.: Uploades min liste nogen steder?
Sv.: Nej. Dette værktøj er 100 % klientside - din liste, din seed og outputtet forlader aldrig din browser. Der er ingen serverkald, ingen logning og ingen analyse af inputtet. Du kan koble fra internettet, efter siden er indlæst, og hver knap virker stadig. Genindlæs siden, og dataene er væk for altid.
Sp.: Findes der en visuel lykkehjul-version af dette værktøj?
Sv.: For en interaktiv navnehjuls-oplevelse med animation, lydeffekter og en stor visuel afsløring, se randompickerwheel.app. Det er et supplerende produkt med fokus på live trækninger foran publikum og skærmdeling. Denne side er en tekst-først-udvælger med fokus på store lister, reproducerbare trækninger med seed, CSV-eksport og parring - nyttig, når du har brug for et hurtigt deterministisk svar frem for en præsentation.