javascript如何在一个数组里随机选出不重复的10项?

[1,2,3,4,5,6,7,8,9,10,11,12,13,14]
在这个数组里选出10项不重复

阅读 20.6k
13 个回答
var result = [];
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
var len = arr.length;
while(result.length < 10){
    var idx = parseInt(Math.random()*1000)%len ;
    if(arr[idx]){
        result.push(arr[idx]);
        arr[idx] = undefined;
    }
}

性能确实不如 @边城 的方法,我再添加一个性能更差但是简单的。

arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
arr.sort(function(){return 0.5-Math.random();}).slice(0,10);

业余前端选手,从来不考虑性能。。。

2022-03-16 更新

关于这个算法,专门写了一篇:从数据集中随机抽取一定数量的数据,其中包含不修改原数组的方法(还是从 Fisher-Yates 算法演变的)


来试试这个

var result = [];
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];

var count = arr.length;
for (var i = 0; i < 10; i++) {
    var index = ~~(Math.random() * count) + i;
    result[i] = arr[index];
    arr[index] = arr[i];
    count--;
}

console.log(result);

算法简述:

把源数组分成左右两段,左边按顺序递增,保存已选择的随机数;右侧是剩余可选的数值;每次从右侧选一个,与左侧最后一个位置的数值交换就可以达到目的。

然后考虑把左侧用一个新数组表示,右侧选中的数移入新数组,再将左侧应该交换过来的值移过来……

来张某次运行示意图

clipboard.png

var arr=[1,2,3,4,5,6,7,8,9,10,11,12,13,14];
var myarr=[];
for(var i=0;i<10;i++){
    var idx=parseInt(Math.random()*arr.length)
    myarr.push(arr[idx])
    arr.splice(idx,1)    
}
function getTenNum(n) {
    var reslut = [];
    var testArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
    for (var i = 0; i < n; ++i) {
        var random = Math.floor(Math.random() * testArray.length);
        reslut.push(testArray[random]);
        testArray.splice(random,1);
    }
    return reslut;        
}
var resArr = getTenNum(10);
这个 应该 是大多数人的 代码
 var result = [], tmp = [],
    arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
    len = arr.length;
    for(var i = 0; result.length < 10; i++){
        var random = Math.floor(Math.random() * len);
        if(!tmp[random]){
           tmp[random] = 1;
            result.push(arr[random])
        } else {
           continue;
        }
    }
    console.log(result)

循环次数少,还可以统计数组的重复元素等
这个方法可以用于数组去重统计数组中出现最多的元素个数,输出tmp数组里面可以得出,需要什么输出什么就行了

用lodash库,或underscore库
var _ = require("underscore");

var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];

var newArr = _.shuffle(arr);

console.log(newArr.slice(0,10));
console.log(newArr.slice(0,10).length);

思路很简单啊,就好比你现在手里有14个数字,你就从里面拿呗,拿走了一个之后肯定就少一个了。
这样怎么拿都是不重复的啊。

可以用堆栈啊 将数组存储在堆栈里面,pop和push都是随机的就行。随机方法可以取随机数然后对2取余。

可以对前10个元素进行遍历,随机选取十个前十个之后的元素,进行交换,最后截取前十个元素就可以了
复杂度:
O(10)

新手上路,请多包涵

1、按下标找到第一个;
2、将此下标和最后一个交换;
3、在总长度-1中查找下一个;
4、将此下标和倒数第二个交换;
...
5、重复四次;
6、该数组前十个及所需;

如果数字的范围比较小,可以参考计数排序。

先去重,再用underscore库shuffle洗牌

_.shuffle(_.uniq([1,2,3,4]))
function getArrCount(arr, count) {
    let result = [];
    let i = 0;

    while (i < count) {
        let num = Math.floor(Math.random() * arr.length);

        if (!result.includes(arr[num])) {
            result.push(arr[num]);
            i++;
        }
        
        return result;
    }
}

var a = getArrCount([1,2,3,4,5,6,7,8,9,10,11,12,13,14], 10);

console.log(a);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏