Weighted random

Run Settings
LanguageC#
Language Version
Run Command
using System; using System.Linq; using System.Collections.Generic; public class WeightedItem<T> { public T Item { get; set; } public double Weight { get; set; } = 1; } class WeightedRandom<T> { private static Random random = new Random(); private List<WeightedItem<T>> list { get; set; } = new List<WeightedItem<T>>(); public WeightedItem<T> this[T item] => list.FirstOrDefault(x => x.Item.Equals(item)) ?? ((Func<WeightedItem<T>>)(() => { list.Add(new WeightedItem<T>{ Item = item }); return this[item]; }))(); public double TotalWeight => list.Sum(x => x.Weight); public WeightedRandom(params T[] items) => list.AddRange(items.Select(x => new WeightedItem<T> { Item = x })); public WeightedRandom(IEnumerable<T> items):this(items.ToArray()) {} public T Next() { var limit = list.Sum(x => x.Weight); var value = random.NextDouble() * limit; var e = list.GetEnumerator(); while(e.MoveNext()) if((e.Current.Weight) > value) return e.Current.Item; else value -= e.Current.Weight; return e.Current.Item; } } class MainClass { static void Main() { var items = new[] { "Sam", "Lia", "Kind Lenny", "Boomer Badlad", "Handsum Jim" }; var occurs = new Dictionary<string, int>(); var rand = new WeightedRandom<string>(items); rand["Sam"].Weight = 5; rand["Handsum Jim"].Weight = .5; var length = rand.TotalWeight * 1000000; for(var i = 0; i < length; i++) { var item = rand.Next(); if(occurs.ContainsKey(item)) occurs[item]++; else occurs[item] = 1; } foreach(var item in items) Console.WriteLine($"{item}: {occurs[item]}"); } }
Editor Settings
Theme
Key bindings
Full width
Lines