hi,欢迎访问本站!
当前位置: 首页学习笔记正文

如何从数组中随机取出多个不重复的项

用户投稿 学习笔记 12阅读
1.问题 如何随机取数组中的多个值?给定一个数组,需要从此数组中 随机取出 不重复的 几项; 2.应用举例 从20个会员中,随机抽出5个做为幸运奖; 对于这个应用,一个办法是可以在数据库层面解决,如(sql server): select top 5 * from  (select top 20 * from userid order by userid desc) as b order by newid() 可是有时候,我们需要在编程语言中完成这样的功能,而不是从数据库,下边说的就是使用编程语言实现的方法; 3.实现思路 思路一:写一个无限循环,或者数组长度的循环,使用随机函数,每次从数组中随机抽取1项,同时判断此项是否已被抽取,如果被抽取,则继续循环重新抽取,直到取出不重复5项时,跳出循环; 这办法简单吧?但这个办法不太好,如果需求要求从10万个中随机取出1万个,使用此办法,那么将有1/10的概率每次都取出了曾经取出的那项了,于是需要重新再取,效率自然不高。另外,无限循环或循环数组长度次总让人心里觉得不踏实。 思路二:写一个循环,循环次数为要取出的个数,即取几个就刚好循环几次,每取一次,将取出的项从数组中删除,下次循环再取时,保证不会重复,少了是否重复的判断。 4.几种语言的实现代码 这里采用第二种思路,下面有as,js,C#的实现代码。 ActionScript 2.0代码: // 从一个给定的数组arr中,随机返回num个不重复项 function  getArrayItems(arr:Array, num:Number):Array {     // 新建一个数组,将传入的数组复制过来,用于运算,而不要直接操作传入的数组;      var  temp_array:Array  =   new  Array();    for (var index in arr) {        temp_array.push(arr[index]);    }      // 取出的数值项,保存在此数组      var  return_array:Array  =   new  Array();     for  ( var  i  =   0 ; i < num; i ++ ) {         // 判断如果数组还有可以取出的元素,以防下标越界          if  (temp_array.length > 0 ) {             // 在数组中产生一个随机索引              var  arrIndex:Number  =  Math.floor(Math.random() * temp_array.length);             // 将此随机索引的对应的数组元素值复制出来             return_array[i]  =  temp_array[arrIndex];             // 然后删掉此索引的数组元素,这时候temp_array变为新的数组             temp_array.splice(arrIndex,  1 );        }  else  {             // 数组中数据项取完后,退出循环,比如数组本来只有10项,但要求取出20项.              break ;        }    }     return  return_array;} // 测试 var  my_array:Array  =   new  Array(); for  ( var  i  =   0 ; i < 20 ; i ++ ) {    my_array[i]  =   " Num: " + i;}my_array  =  getArrayItems(my_array,  5 ); for  ( var  i  =   0 ; i < my_array.length; i ++ ) {    trace(my_array[i]);} JavaScript代码,和AS类似: < script language = " javascript " > // 从一个给定的数组arr中,随机返回num个不重复项 function  getArrayItems(arr, num) {     // 新建一个数组,将传入的数组复制过来,用于运算,而不要直接操作传入的数组;      var  temp_array  =   new  Array();    for (var index in arr) {        temp_array.push(arr[index]);    }      // 取出的数值项,保存在此数组      var  return_array  =   new  Array();     for  ( var  i  =   0 ; i < num; i ++ ) {         // 判断如果数组还有可以取出的元素,以防下标越界          if  (temp_array.length > 0 ) {             // 在数组中产生一个随机索引              var  arrIndex  =  Math.floor(Math.random() * temp_array.length);             // 将此随机索引的对应的数组元素值复制出来             return_array[i]  =  temp_array[arrIndex];             // 然后删掉此索引的数组元素,这时候temp_array变为新的数组             temp_array.splice(arrIndex,  1 );        }  else  {             // 数组中数据项取完后,退出循环,比如数组本来只有10项,但要求取出20项.              break ;        }    }     return  return_array;} // 测试 var  my_array  =   new  Array(); for  (i  =   0 ; i  <   20 ; i ++ ){   my_array[i]  =   " Num: " + i;}my_array  =  getArrayItems(my_array, 5 ); for  (i  =   0 ; i  <  my_array.length; i ++ ){   alert(my_array[i]);} </ script > C#代码:          public   static  IList < string >  getListItems(IList < string >  list,  int  num)         {            //新建一个泛型列表,将传入的列表复制过来,用于运算,而不要直接操作传入的列表;                //这样写是引用复制,不对啦,谢谢Osamede指出.            //IList<string> temp_list = list;            //另外这样写也要注意,也不是深度复制喽,关于深度复制可以做为一个新话题来说,这儿就不说啦;            IList<string> temp_list = new List<string>(list);            //取出的项,保存在此列表            IList<string> return_list = new List<string>();            //Random random = new Random(unchecked((int)DateTime.Now.Ticks));            Random random = new Random();            for (int i = 0; i < num; i++)            {                //判断如果列表还有可以取出的项,以防下标越界                if (temp_list.Count > 0)                {                    //在列表中产生一个随机索引                    int arrIndex = random.Next(0, temp_list.Count);                    //将此随机索引的对应的列表元素值复制出来                    return_list.Add(temp_list[arrIndex]);                    //然后删掉此索引的列表项                    temp_list.RemoveAt(arrIndex);                }                else                {                    //列表项取完后,退出循环,比如列表本来只有10项,但要求取出20项.                    break;                }            }            return return_list;        } 测试: static   void  Main( string [] args)         {            IList<string> temp_list = new List<string>();            for (int i = 0; i < 20; i++)            {                temp_list.Add("Num:" + i.ToString());            }            temp_list = getListItems(temp_list, 5);            for (int i = 0; i < temp_list.Count; i++)            {                WL(temp_list[i]);            }            RL();        }          Helper methods #region Helper methods        private static void WL(object text, params object[] args)        {            Console.WriteLine(text.ToString(), args);        }        private static void RL()        {            Console.ReadLine();        }        private static void Break()        {            System.Diagnostics.Debugger.Break();        }        #endregion
标签:
声明:无特别说明,转载请标明本文来源!
发布评论
正文 取消