Är kanske bara morgontrött men kommer inte på någon smart lösning på det här. 1. Sortera listan på tyngden Borde man inte kunna göra så här: 1. Lägg ihop alla vikter till en total * Skapa en tmp.lista. Henriks variant är rätt. Dan, Jonas: Vad gör ni om man får vikten 2.37? Tack Henrik, tror din lösning är den bästa ifall att jag behöver använda mig av decimaler i vikterna. En sak förstår jag dock inte; Varför ska man sortera arrayen med högst först? Blir inte resultatet det samma oberoende av ordning på elementen i arrayen? Behövs inte, men bör göra urvalet lite snabbare. Ok då är det inga problem:) Ja det har jag tänkt så tänkte att jag slumpar listans ordning innan jag kör den så inte alltid samma item ligger sist. Jo, men om man sätter de som har störst chans först så försvinner så mycket som möjligt av värdet också först.Slumpa med tyngd
Jag har en lista/array med objekt, varje objekt har ev viss tyngd som ska öka chansen att just det objektet väljs från listan. Detta tyngd-värde kan som minst vara 100 (eller 1 om man föredrar det) men har ingen övre gräns.
Frågan är nu hur jag gör för att slumpa fram ett av objekten men ge proportionellt större chans åt de med större tyngd.
Jag är inte ute efter någon perfekt fungerande kod utan undrar bara hur jag ska gå till väga.Sv: Slumpa med tyngd
2.a och ta det översta elementet =)
2.b eller slumpa på översta hälften för att 50% ska ha en större chans.
Om jag nu har förstått ditt problem ordentligt såhär tidigt på morgonen XDSv: Slumpa med tyngd
1. Loopa igenom arrayen och lägg till id't X antal gånger i en slump-array, där X är vikten
2. Slumpa fram ett id från slump-arrayenSv: Slumpa med tyngd
2. Slumpa fram ett nummer mindre än "total"
3. Gå igenom arrayen i ordning högsta vikt till minsta vikt, dra ifrån vikten från random-värdet, när random värdet är negativt, returnera den ordningen i listan/arrayen
Lite Javascript som illustrerar det hela, namnen är heeeeelt och hållet påhittade och har ingen koppling till personer på forumet;
function chooseWeighted(arr) {
var num = arr.length, total = 0;
for (var i=0; i<num; i++) {
total += arr[i][1];
}
i = -1;
var random = Math.floor(Math.random()*total);
while (random > 0) {
random -= arr[++i][1];
}
return arr[i];
}
var weights = [['Malm Henrikberg', 10], ['Sjö Jonasblom', 7], ['Johan Ericsson', 5], ['Therkild Dansen', 5], ['Johan Persson', 2], ['Per-Åke Svensson', 0]];
var thechoosen = chooseWeighted(weights);
alert(thechoosen[0]);
Sv: Slumpa med tyngd
* från org.listan infoga antal element till tmp.listan baserat på tyngden.
* slumpa från tmp.listan.Sv:Slumpa med tyngd
Det enklaste, tankemässigt är nog: lägg ihop alla vikter till en total. Dividera varje vikt med denna total. Då får man alla som var sin andel (tar man gånger 100 får man procentsats).
Lägg sen alla efter varandra och slumpa fram en plats mellan 0 och 1, den som ligger där blir vald. (Och det gör man med Henriks kod)Sv: Slumpa med tyngd
Sv:Slumpa med tyngd
Kommer du hämta många gånger från samma lista?Sv: Slumpa med tyngd
Men vid närmare eftertanke borde det ju inte spela någon roll om samma alltid blir sist, det har ändå samma chans att bli valt.Sv:Slumpa med tyngd
Tänk att du har 11 stycken, 10 med 1% och en med 90%. Tänk då att du sorterar dem stigande.
Allt mellan 10% och 100% innebär då att du måste gå igenom hela listan (och kommer fram till den stora).
Vänder du på sorteringen så kommer du fram till den stora på 0-90%, och behöver bara gå igenom en enda.
Sen kommer ju förstås tiden till sorteringen in, och därför är det relevant om du använder samma lista många gånger. Annars är det waste att sortera den först.
Och slutligen är det väl extremt osannolikt att detta är så prestandakrävande att det spelar någon som helst roll... =)