Beispiel #1
0
        /// <summary>
        /// Gets an enumerator that enumerates elements of the <see cref="System.Collections.Generic.IEnumerable{T}" /> sequence in a random manner.
        /// </summary>
        /// <typeparam name="T">The type of elements in the sequence.</typeparam>
        /// <param name="sequence">The enumerable sequence.</param>
        /// <param name="algorithm">The algorithm used to prevent an element from being accessed twice.</param>
        /// <param name="random">A <see cref="System.Random" /> object that generates random numbers.
        /// If this argument is not specified, a new <see cref="System.Random" /> instance will be used.</param>
        /// <returns>
        /// An enumerator that randomly enumerates elements of the sequence.
        /// </returns>
        public static IEnumerator <T> GetRandomEnumerator <T>(this IEnumerable <T> sequence,
                                                              DistinctRandomAlgorithms algorithm = DistinctRandomAlgorithms.Auto, Random random = null)
        {
            var range = sequence.Count();
            var count = range;

            if (random == null)
            {
                random = new Random();
            }

            switch (algorithm)
            {
            default:
            {
                var ratio = (double)count / range;
                if (ratio > 0.2)
                {
                    goto case DistinctRandomAlgorithms.Swap;
                }
                else
                {
                    goto case DistinctRandomAlgorithms.SimpleHash;
                }
            }

            case DistinctRandomAlgorithms.SimpleHash:
            {
                var hasheset = new HashSet <int>();
                while (count != 0)
                {
                    --count;
                    int val;
                    do
                    {
                        val = random.Next(0, range);
                    }while (hasheset.Contains(val));
                    hasheset.Add(val);
                    yield return(sequence.ElementAt(val));
                }

                break;
            }

            case DistinctRandomAlgorithms.Swap:
            {
                var tempArr = new int[range];
                int val;

                while (count != 0)
                {
                    val = random.Next(0, range);
                    --range;
                    --count;

                    if (tempArr[val] == 0)
                    {
                        yield return(sequence.ElementAt(val));
                    }
                    else
                    {
                        yield return(sequence.ElementAt(tempArr[val]));
                    }

                    tempArr[val] = tempArr[range] == 0 ? range : tempArr[range];
                }

                break;
            }

            case DistinctRandomAlgorithms.SwapHash:
            {
                var dict = new Dictionary <int, int>();
                int val;

                while (count != 0)
                {
                    val = random.Next(0, range);
                    --range;
                    --count;

                    int tval1, tval2;
                    var exist1 = dict.TryGetValue(val, out tval1);
                    var exist2 = dict.TryGetValue(range, out tval2);

                    if (exist1)
                    {
                        dict[val] = exist2 ? tval2 : range;
                        yield return(sequence.ElementAt(tval1));
                    }
                    else
                    {
                        dict.Add(val, exist2 ? tval2 : range);
                        yield return(sequence.ElementAt(val));
                    }
                }

                break;
            }
            }
        }
Beispiel #2
0
 /// <summary>
 /// Gets an enumerator that enumerates all elements of the array in a random manner.
 /// </summary>
 /// <typeparam name="T">The type of elements in the array.</typeparam>
 /// <param name="array">The array.</param>
 /// <param name="algorithm">The algorithm used to prevent an element from being accessed twice.</param>
 /// <param name="random">A <see cref="System.Random" /> object that generates random numbers.
 /// If this argument is not specified, a new <see cref="System.Random" /> instance will be used.</param>
 /// <returns>
 /// An enumerator that randomly enumerates elements of the array.
 /// </returns>
 public static IEnumerator <T> GetRandomEnumerator <T>(this T[] array,
                                                       DistinctRandomAlgorithms algorithm = DistinctRandomAlgorithms.Auto, Random random = null)
 {
     return(GetRandomEnumerator <T>(array, array.Length, algorithm, random));
 }
Beispiel #3
0
 /// <summary>
 /// Gets an enumerator that enumerates all elements of the <see cref="System.Collections.Generic.IList{T}"/> in a random manner.
 /// </summary>
 /// <typeparam name="T">The type of elements in the list.</typeparam>
 /// <param name="array">The list.</param>
 /// <param name="algorithm">The algorithm used to prevent an element from being accessed twice.</param>
 /// <param name="random">A <see cref="System.Random" /> object that generates random numbers.
 /// If this argument is not specified, a new <see cref="System.Random" /> instance will be used.</param>
 /// <returns>
 /// An enumerator that randomly enumerates elements of the list.
 /// </returns>
 public static IEnumerator <T> GetRandomEnumerator <T>(this IList <T> list,
                                                       DistinctRandomAlgorithms algorithm = DistinctRandomAlgorithms.Auto, Random random = null)
 {
     return(GetRandomEnumerator <T>(list, list.Count, algorithm, random));
 }
Beispiel #4
0
        /// <summary>
        /// Gets an enumerator that enumerates elements of the array in a random manner.
        /// </summary>
        /// <typeparam name="T">The type of elements in the array.</typeparam>
        /// <param name="array">The array.</param>
        /// <param name="count">The total number of elements the enumerator should enumerate before reset.</param>
        /// <param name="algorithm">The algorithm used to prevent an element from being accessed twice.</param>
        /// <param name="random">A <see cref="System.Random" /> object that generates random numbers.
        /// If this argument is not specified, a new <see cref="System.Random" /> instance will be used.</param>
        /// <returns>An enumerator that randomly enumerates elements of the array.</returns>
        public static IEnumerator <T> GetRandomEnumerator <T>(this T[] array, int count,
                                                              DistinctRandomAlgorithms algorithm = DistinctRandomAlgorithms.Auto, Random random = null)
        {
            var range = array.Length;

            if (random == null)
            {
                random = new Random();
            }

            switch (algorithm)
            {
            default:
            {
                var ratio = (double)count / range;
                if (ratio > 0.2)
                {
                    goto case DistinctRandomAlgorithms.Swap;
                }
                else
                {
                    goto case DistinctRandomAlgorithms.SimpleHash;
                }
            }

            case DistinctRandomAlgorithms.SimpleHash:
            {
                var hasheset = new HashSet <int>();
                while (count != 0)
                {
                    --count;
                    int val;
                    do
                    {
                        val = random.Next(0, range);
                    }while (hasheset.Contains(val));
                    hasheset.Add(val);
                    yield return(array[val]);
                }

                break;
            }

            case DistinctRandomAlgorithms.Swap:
            {
                var tempArr = new int[range];

                int val;
                var length2 = count;         //max is used to store "length" here

                while (count != 0)
                {
                    val = random.Next(0, range);
                    --range;
                    --count;

                    if (tempArr[val] == 0)
                    {
                        yield return(array[val]);
                    }
                    else
                    {
                        yield return(array[tempArr[val]]);
                    }

                    tempArr[val] = tempArr[range] == 0 ? range : tempArr[range];
                }

                break;
            }

            case DistinctRandomAlgorithms.SwapHash:
            {
                var dict = new Dictionary <int, int>();
                int val;

                while (count != 0)
                {
                    val = random.Next(0, range);
                    --range;
                    --count;

                    int tval1, tval2;
                    var exist1 = dict.TryGetValue(val, out tval1);
                    var exist2 = dict.TryGetValue(range, out tval2);

                    if (exist1)
                    {
                        dict[val] = exist2 ? tval2 : range;
                        yield return(array[tval1]);
                    }
                    else
                    {
                        dict.Add(val, exist2 ? tval2 : range);
                        yield return(array[val]);
                    }
                }

                break;
            }
            }
        }