Hm, here alone with Seq.scan, but it also feels very ugly ...
type WeightedItem(id: int, weight: int) = member self.id = id member self.weight = weight let selectItem (items: WeightedItem list) (rand:System.Random) = let totalWeight = List.sumBy (fun (item: WeightedItem) -> item.weight) items let selection = rand.Next(totalWeight) + 1 Seq.scan (fun (runningWeight,found,itemO) (item: WeightedItem) -> if not found then let newRunningWeight = runningWeight + item.weight newRunningWeight, newRunningWeight >= selection, Some(item) else (runningWeight,found,itemO)) (0,false,None) items |> Seq.find (fun (rw,f,i) -> f) |> (fun (rw,f,i) -> i.Value) let items = [new WeightedItem(1,100) new WeightedItem(2,50) new WeightedItem(3,25)] let selection = selectItem items (new System.Random())
source share