/// <summary> /// Re/Builds internal CDL (Cummulative Distribution List) /// Must be called after modifying (calling Add or Remove), or it will break. /// Switches between linear or binary search, depending on which one will be faster. /// Might generate some garbage (list resize) on first few builds. /// </summary> /// <param name="seed">You can specify seed for internal random gen or leave it alone</param> /// <returns>Returns itself</returns> public IRandomSelector <T> Build(Int32 seed = -1) { if (_items.Count == 0) { throw new Exception("Cannot build with no items."); } // clear list and then transfer weights _cdl.Clear(); foreach (Double weight in _weights) { _cdl.Add(weight); } RandomMath.BuildCumulativeDistribution(_cdl); // default behavior // if seed wasn't specified (it is seed==-1), keep same seed - avoids garbage collection from making new random if (seed != -1) { // input -2 if you want to randomize seed if (seed == -2) { seed = _random.Next(); } _random = RandomUtils.Create(seed); } // RandomMath.ListBreakpoint decides where to use Linear or Binary search, based on internal buffer size // if CDL list is smaller than breakpoint, then pick linear search random selector, else pick binary search selector if (_cdl.Count < RandomMath.ListBreakpoint) { _select = RandomMath.SelectIndexLinearSearch; } else { _select = RandomMath.SelectIndexBinarySearch; } return(this); }
/// <summary> /// Builds StaticRandomSelector & clears internal buffers. Must be called after you finish Add-ing items. /// </summary> /// <param name="seed">Seed for random selector. If you leave it -1, the internal random will generate one.</param> /// <returns>Returns IRandomSelector, underlying objects are either StaticRandomSelectorLinear or StaticRandomSelectorBinary. Both are non-mutable.</returns> public IRandomSelector <T> Build(Int32 seed = -1) { T[] items = _items.ToArray(); Double[] cda = _weights.ToArray(); _items.Clear(); _weights.Clear(); RandomMath.BuildCumulativeDistribution(cda); if (seed == -1) { seed = _random.Next(); } // RandomMath.ArrayBreakpoint decides where to use Linear or Binary search, based on internal buffer size // if CDA array is smaller than breakpoint, then pick linear search random selector, else pick binary search selector if (cda.Length < RandomMath.ArrayBreakpoint) { return(new StaticRandomSelectorLinear <T>(items, cda, seed)); } return(new StaticRandomSelectorBinary <T>(items, cda, seed)); }