再来写一个随机数解决方案,对Random再来一次封装

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了再来写一个随机数解决方案,对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;
            }
        }

     

  • 大家试试吧,真的挺好用的

以上是关于再来写一个随机数解决方案,对Random再来一次封装的主要内容,如果未能解决你的问题,请参考以下文章

深拷贝呀,浅拷贝,再来一次复习整理

原创答《读研or工作?对计算机类专业学习的看法》---如果再来一次,我不会读研!

再来一次手牵手:php7.0 + protobuf

警惕年底再来一次“压力测试”| 12月08日银行同业报价及分析

如果再来一次,你还会选择互联网么?

如果再来一次,你还会选择互联网么?