天天看點

再來寫一個随機數解決方案,對Random再來一次封裝

本文提供對Random的封裝,簡化并擴充了其功能

  • 擷取随機數,確定同時調用不會重複
    //new Random().Next(5);
     RandomTask.Next(5);      
  • 從一個清單中,随機擷取其中某個值
    List<string> lsTest = new List<string>
                {
                    "1","2","3","4","5"
                };
                string randomValue = RandomTask.PickOne(lsTest);
                Console.WriteLine(randomValue);      
  • 從一個清單中,随機擷取其中多個值
    List<string> someRandomValue = RandomTask.PickAny(lsTest, 3);
    Console.WriteLine(string.Join(",", someRandomValue));      
  • 想按某個機率傳回bool值,可以這麼寫
    bool is30Per = RandomTask.PickBoolByProp(0.3);
                Console.WriteLine(is30Per);      
  • 最複雜的,一個list中有a,b兩個資料,a按照70%機率傳回而b按30%傳回,就這樣寫
    Dictionary<string, double> lsTestAB = new Dictionary<string, double>
                {
                    {"A",0.7 },
                    { "B",0.3}
                };
                string aOrb = RandomTask.PickOneByProb(lsTestAB);
                Console.WriteLine(aOrb);      
  • 源碼
    public static class RandomTask
        {
            private static readonly Random _random = new Random();
    
            public static int Next()
            {
                lock (_random)
                {
                    return _random.Next();
                }
            }
    
            public static int Next(int max)
            {
                lock (_random)
                {
                    return _random.Next(max);
                }
            }
    
            public static int Next(int min, int max)
            {
                lock (_random)
                {
                    return _random.Next(min, max);
                }
            }
    
            /// <summary>
            /// 按機率擷取
            /// </summary>
            /// <param name="trueProp"></param>
            /// <returns></returns>
            public static bool PickBoolByProp(double trueProp = 1)
            {
                if (trueProp > 1)
                {
                    trueProp = 1;
                }
                if (trueProp < 0)
                {
                    trueProp = 0;
                }
                Dictionary<bool, double> wt = new Dictionary<bool, double>
                {
                   { true , trueProp },
                   { false , 1 - trueProp }
                };
                return wt.PickOneByProb();
            }
    
            /// <summary>
            /// 按指定機率擷取随機結果
            /// </summary>
            /// <param name="sourceDic">a 0.8 b 0.1 c 0.1</param>
            /// <returns>随機結果 [a,b,c]</returns>
            public static T PickOneByProb<T>(this Dictionary<T, double> sourceDic)
            {
                if (sourceDic == null || !sourceDic.Any())
                {
                    return default(T);
                }
    
                int seed = (int)(10 / (sourceDic.Values.Where(c => c > 0).Min()));
                int maxValue = sourceDic.Values.Aggregate(0, (current, d) => current + (int)(seed * d));
    
                int rNum = Next(maxValue);
                int tem = 0;
                foreach (KeyValuePair<T, double> item in sourceDic)
                {
                    tem += (int)(item.Value * seed);
                    if (tem > rNum)
                    {
                        return item.Key;
                    }
                }
                return default(T);
            }
    
            /// <summary>
            /// 随機從List中擷取一項
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="source"></param>
            /// <returns></returns>
            public static T PickOne<T>(this List<T> source)
            {
                if (source == null || !source.Any())
                {
                    return default(T);
                }
                return source[Next(source.Count)];
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="source"></param>
            /// <param name="c"></param>
            /// <returns></returns>
            public static List<T> PickAny<T>(this List<T> source, int c)
            {
                if (source == null || !source.Any())
                {
                    return default(List<T>);
                }
                if (source.Count <= c)
                {
                    return source;
                }
                List<T> ls = new List<T>();
                for (int i = 0; i < c; i++)
                {
                    var t = source.PickOne();
                    if (!ls.Contains(t))
                    {
                        ls.Add(t);
                    }
                }
                return ls;
            }
        }      
  • 大家試試吧,真的挺好用的