/// <summary> /// Updates the sample set adding the specified value using <see href="http://www.cs.umd.edu/~samir/498/vitter.pdf">Vitter's Algorithm R</see>. /// </summary> /// Algorithm R pseudo code /// <example> /// <code> /// <![CDATA[ /// -- S has items to sample, R will contain the result /// ReservoirSample(S[1..n], R[1..k]) /// -- fill the reservoir array /// for i = 1 to k /// R[i] := S[i] /// -- replace elements with gradually decreasing probability /// for i = k+1 to n /// j := random(1, i) -- important: inclusive range /// if j <= k /// R[j] := S[i] /// ]]> /// </code> /// </example> /// <param name="value">The value to add to the sample set.</param> /// <param name="userValue">The user value to track, which records the last, min and max user values within the sample.</param> public void Update(long value, string userValue = null) { var c = _count.Increment(); if (c <= _values.Length) { _values[(int)c - 1] = new UserValueWrapper(value, userValue); } else { var r = ThreadLocalRandom.NextLong(c); if (r < _values.Length) { _values[(int)r] = new UserValueWrapper(value, userValue); } } }
public bool Equals(UserValueWrapper other) { return(string.Equals(UserValue, other.UserValue) && Value == other.Value); }