从一个包含1000个元素的数组中随机选择50个不同的元素?

5
从一个包含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.

2
什么是唯一元素?你是指索引中的唯一索引还是唯一值? - epascarello
7个回答

4
明显(对我来说)的方法是打乱数组,然后取前50个元素。这个问题有一个很好的方法来打乱一个数组,然后你可以使用slice选取前50个元素。这保证了元素是唯一的。
因此,可以使用该函数:
fisherYates(text);
text = text.slice(0, 50);

1
不错的想法!但是,它只有在那1000个元素是唯一的情况下才能起作用。 - VisioN
@VisioN 在这种情况下,请确保text中的元素是唯一的。有很多可用的函数可以精确地执行此操作,例如这个 - lonesomeday
VisioN是正确的,而且对于洗牌1000个长度的数组来说代价很高。 - ajax333221
1
仅运行50个周期的洗牌算法。 - Karoly Horvath

1

这个主题中解释了很好的算法(用C语言解释,但你可以轻松地在JS中实现同样的效果)


0

如果您的意思是唯一值:

演示

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;
}

如果你指的是唯一索引:

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

0
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]);
}

假设“text”是一个包含1000个值的数组


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

0

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

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

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)),但我猜这也应该可以运行。 - ajax333221

0

-2

Math.random() * 1000;

生成50个随机数,并将它们用作数组中的位置。


我在这里做一些假设。我假设你正在检查你的随机值,就像我假设你知道如何存储那五十个数字,而不需要我向你展示 :) - Limey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接