从数组中选择一个随机值,该值不在数组中。

5
我该如何选择一个不在此数组中的随机值(0到30)?
var list = new Array(1,3,4,7,8,9);

我的问题有点开放性,我很抱歉。我正在寻找不同的选项和线索。 - Sparkup
8个回答

8
构建补充数组并从中随机选择值。
var list2 = new Array();
for(var i=0; i<30; i++)
  if(!list.contains(i))
    list2.push(i);

然后:

var rand = list2[Math.floor(Math.random() * list2.length)];

2
function RandomValueNotInArray(array)
{
    var e;
    do
    {
        e = Math.random() * 31; // n + 1
    } while (array.contains(e))
    return e;
}

但是 Math.random 会生成浮点数,应该改为 Math.random()*31 吗? - wizztjh
代码本身就是最好的说明,但为了完整起见,考虑添加一份描述。 - T J
Math.random() 返回一个十进制值。在将其与整数列表进行比较之前,您需要使用 Math.trunc()Math.floor() 对返回值进行处理,否则它永远不会匹配。 - OOPS Studio

1
你需要一个while循环来测试rand是否在restricted数组中,如果是,则重新生成一个新的随机数:
var rand;
do {
    rand = Math.floor(Math.random() * 31); // re-randomize, 0 to 30 inclusive
} while ($.inArray(rand, restricted) > -1);
return rand;

http://jsfiddle.net/mblase75/dAN8R/

不想使用jQuery吗?如果您使用旧浏览器的此polyfill,则可以将$.inArray(rand,restricted)替换为restricted.indexOf(rand)

这不是和这个回答 https://dev59.com/MVrUa4cB1Zd3GeqPgAgh#6979340 几乎在两年前发布的一样吗? - T J
@TJ 如果array.contains()是一个内置方法或者Math.random() * 31不是浮点数的话,那可能会是这样。 - Blazemonger

1
假设您的列表大小相对较小,请创建一个数字列表,其中不包含数组中的数字,然后随机从该列表中选择一个数字。

1
一个小递归函数:
getNum() {
  let randomNum = Math.floor(Math.random() * (30 - 1)) + 1
  if (list.includes(randomNum)) {
    return getNum()
  }
   return randomNum
}

这可能会更快,因为它首先尝试返回一个随机数,然后检查它是否在数组中。


当排除数组中的元素数量增加时,性能如何?当可能范围从30增长到30,000,然后再增长到30,000,000时,这种策略的表现如何? - Jason Aller
感谢您的提问,我进行了一些测试。使用递增的随机数数组,并将递归与@slaphappy的互补数组(最受欢迎的解决方案)进行了比较。参数(生成数量/数组大小): (1000个中的1个)递归~ 0.015毫秒/互补:~ 1.25、1.26毫秒 (10000个中的1个)递归~ 0.030毫秒/互补~ 115毫秒 (100000个中的1个)递归~ 0.44毫秒/互补~ 11573毫秒(或崩溃) (1000个中的1000个)递归~ 4毫秒/互补~ 1182毫秒 (10000个中的10000个)递归~ 317毫秒/互补~ 崩溃 (1000000个中的1000000个)递归~ 31422毫秒/互补~ 没门请注意,递归有时会使其运行时间加倍(当它调用自身时)! - Marianissimus

0

你可以使用过滤器

var filteredArray = list.filter(function(e){
  return e!= Math.floor(Math.random() * (31));

});

你的代码将创建一个包含数组中存在的一些数字的列表。OP想要相反的东西,只有一个不在数组中的数字。 - Shamim Hafiz - MSFT

0

我可能会从中创建一个数组或链表,然后减去不需要的项目。这样,我可以继续删除项目,并且只需随机选择从位置0到数组长度-1的项目,而无需选择相同的内容两次。

另一种方法是在0到30之间随机生成一个数字,并在数组中找到它时继续执行。唯一的问题是知道何时数组已满(以消除无限循环),并且它需要更多的处理器资源。


-1

2行PHP代码:

$result = array_diff(range(1,30), array(1,3,4,7,8,9)); 
echo $result[array_rand($result)];

如果这个问题之前被标记为PHP,现在已经不是了。 - Blazemonger
只是想帮助那些从谷歌搜索到这里的人。 - MPaulo

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