再来写一个随机数解决方案,对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; } }
- 大家试试吧,真的挺好用的