【问题标题】:50 random unique elements from an array of 1000 elemens?来自 1000 个元素的数组中的 50 个随机唯一元素?
【发布时间】:2012-05-28 02:49:06
【问题描述】:

从 1000 个元素的数组中获取 50 个随机唯一元素的最简单方法是什么?

text = new Array();
for(i=0;i<1000;i++){ text[i]=i; }   //array populated
// now I need to get 50 random unique elements from this array.

【问题讨论】:

  • 独特元素是什么意思?您的意思是唯一索引或索引中的唯一值?

标签: javascript arrays random


【解决方案1】:

Math.random() * 1000;

生成50个随机数,作为数组中的位置。

【讨论】:

  • 我在这里做一些假设。我假设您正在检查您的随机值,就像我假设您知道如何存储这 50 个数字而没有我向您展示 :)
【解决方案2】:

this topic 中解释了好的算法(在 C 中,但您可以在 JS 中轻松地做同样的事情)

【讨论】:

    【解决方案3】:

    (对我而言)显而易见的方法是打乱数组,然后取前 50 个元素。 This question 有一个很好的方法来打乱一个数组,然后你可以 slice 前五十个元素。这保证了元素是唯一的。

    所以,使用那里的功能:

    fisherYates(text);
    text = text.slice(0, 50);
    

    【讨论】:

    • 好主意!但是,只有当这 1000 个元素是唯一的时,它才会起作用。
    • @VisioN 在这种情况下,请确保 text 中的元素是唯一的。有很多函数可以精确地做到这一点,例如this one
    • VisioN 是对的,洗牌一个 1000 len 的数组也很昂贵
    • 只运行 shuffle 算法 50 个周期。
    【解决方案4】:

    查看Fisher-Yates algorithm,我认为这对你有用。

    【讨论】:

      【解决方案5】:

      如果您指的是唯一值:

      Demo

      var old_arr = [0,1,2,3,4,5,6,7,8,9], new_array = [];
      
      for (var i = 0; i < 5; i++) {
          var rand_elem = old_arr[Math.floor(Math.random() * old_arr.length)];
      
          if (arrIndex(old_arr[rand_elem], new_array) == -1) {
              new_array.push(rand_elem);
          } else {
              i--;
          }
      }
      
      function arrIndex(to_find, arr) {//own function for IE support
          if (Array.prototype.indexOf) {
              return arr.indexOf(to_find);
          }
          for (var i = 0, len = arr.length; i < len; i++) {
              if (i in arr && arr[i] === to_find) {
                  return i;
              }
          }
          return -1;
      }
      

      如果您指的是唯一索引:

      • 生成随机索引并将索引存储在数组中并进行检查以防止重复
      • 获取数组元素后开始删除,(如果缓存长度可能会有问题,所以不要)

      【讨论】:

        【解决方案6】:
        var arr = [];
        while(arr.length < 51){
            var ind = Math.floor(Math.random()*1000);
            if(!(ind in arr))
                arr.push(ind)
        }
        

        数组 arr 中有 50 个随机唯一数字,可以用作索引

        编辑:

        正如@ajax333221 提到的,前面的代码不会从数组中获取唯一元素,以防它包含重复项。所以这是修复:

        var result_arr = [];
        while(result_arr.length < 51){
            var ind = Math.floor(Math.random()*1000);
            if(text[ind] && !(text[ind] in result_arr))
                result_arr.push(text[ind]);
        }
        

        作为“文本”填充了 1000 个值的数组

        【讨论】:

        • -1 a) 不能正确生成唯一编号,b) 即使修复它,如果 1k 数组包含重复项,唯一编号也无用
        • 是的,你是对的,我误解了这个问题,我只是想获得 50 个唯一索引号。你为什么说它不能正确生成唯一的数字??
        • @d 因为if(!(ind in arr)) 不是正确的检查,它检查索引是否包含在数组中(不是值)。因此,如果您在第一个循环中添加 23,则 23 将有可能复制接下来的 22 个循环。您可能想改用 indexOf
        【解决方案7】:

        这假设您指的是随机索引,而不是具有唯一值的索引。

        一种方法是复制数组并删除您使用的数组:

        function getRandomIndexes( arr, cnt){
            var randomArr = [],
                arrCopy = arr.slice(),
                i, 
                randomNum ;
            for (i=0;i<arrCopy.length;i++) {
                randomNum = Math.floor( arrCopy.length * Math.random());
                randomArr = randomArr.concat(  arrCopy.splice(randomNum ,1) );
            }    
            return randomArr;
        }
        
        var myNums = [], i, randSet;
        for (i=0;i<10;i++){
            myNums.push(i);
        }
        randSet = getRandomIndexes(myNums, 5);
        

        另一种方法是跟踪您使用的索引并继续查找,直到找到您未使用的索引。我发现 while 循环很可怕,如果随机索引需要接近数组长度,我个人不会使用此解决方案。

        function getRandomIndexes( arr, cnt){
            var randomArr = [],
                usedNums = {},
                x;
            while (randomArr.length<cnt) {
                while (usedNums[x]===true || x===undefined) {
                    x = Math.floor( Math.random() * arr.length);
                }
                usedNums[x] = true;
                randomArr.push( arr[x] );
            }
            return randomArr;
        }
        
        var myNums = [], i, randSet;
        for (i=0;i<10;i++){
            myNums.push(i);
        }
        randSet = getRandomIndexes(myNums, 5);
        

        【讨论】:

        • 有趣,我第一次看到arr.slice()(我总是看到arr.slice(0)),但我想它应该也可以工作
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-16
        • 1970-01-01
        • 2014-06-19
        • 1970-01-01
        • 2019-04-26
        • 2014-07-23
        相关资源
        最近更新 更多