【问题标题】:Javascript: Math.floor(Math.random()*array.length) not producing a random number?Javascript:Math.floor(Math.random()*array.length) 不产生随机数?
【发布时间】:2011-07-13 00:05:10
【问题描述】:

e 上的这个太棒了。

我有 while 循环来生成一个随机数,该随机数与之前生成的任何其他随机数都不相同。随机数用于从对象中选择文本值。

例如:

quoteArray[1] = "some text"
quoteArray[2] = "some different text"
quoteArray[3] = "text again"
quoteArray[4] = "completely different text"
quoteArray[5] = "ham sandwich"

这是一个更大函数的一部分,在该函数循环通过 = quoteArray.length 之后,它会重置并重新开始循环。我遇到的问题是以下代码有时会产生无限循环:

//Note: at this point in the function I have generated a random number once already and stored it in 'randomnumber'
//I use this while statement to evaluate 'randomnumber' until the condition of it NOT being a number that has already been used and NOT being the last number is met.
while(randomnumber === rotationArray[randomnumber] || randomnumber === lastnumber){
    randomnumber = Math.floor(Math.random() * (quoteArray.length));
}

当我 console.log(randomnumber) - 当我陷入循环时 - 结果我只是得到'0'。当卡在循环中时,它看起来好像 Math.floor(Math.random() * (quoteArray.length)) 正在产生一个随机数,而只是无限地产生“0”。

谁能告诉我为什么会遇到这个问题?



编辑:这是完整的相关代码,带有函数 + 变量声明

// 初始化quoteObj的函数 函数quoteObj(文本,cname,ccompany,url,height){ this.text=文本; this.cname=cname; 这个.ccompany=ccompany; 这个.url=url; 这个.高度=高度; } // 使用 XML 表中的报价信息填充我的报价对象。 var qObj = new quoteObj('','','',''); var quoteArray = new Array(); 变量计数器 = 0; //循环遍历每个 XML 项并将数据加载到一个对象中,然后将该对象存储在一个数组中 $.ajax({ 类型:“获取”, url: "quotes.xml", 数据类型:“xml”, 成功:函数(xml){ $(xml).find('quote').each(function(){ quoteArray[counter] = new quoteObj('','','',''); console.log(quoteArray[counter]); quoteArray[counter].text = $(this).find('text').text(); quoteArray[counter].cname = $(this).find('customer_name').text(); quoteArray[counter].ccompany = $(this).find('customer_company').text(); quoteArray[counter].url = $(this).find('project').text(); ++计数器; }); } }); // 这是产生我的无限循环问题的设置。 // 我已经包含了所有其他代码,以防人们想知道有关项目如何初始化等的具体事情。 // 生成一个随机的第一个引号,然后随机遍历整个集合并重新开始。 var randomnumber = Math.floor(Math.random() * (quoteArray.length)); var rotationArray = new Array(quoteArray.length); 变量 v = 0; var lastnumber = -1; bHeight = $('#rightbox').height() + 50; 变量 cHeight = 0; var divtoanim = $('#customerquotes').parent(); //不相关的// // 给内部阴影一个高度,以便溢出隐藏与引号一起使用。 $(divtoanim).css({'height' : bHeight}); // 随机旋转引用函数。 设置间隔(函数(){ 随机数 = Math.floor(Math.random() * (quoteArray.length)); //检查函数循环是否需要从头开始。 if(v == (quoteArray.length)){ 旋转数组.length = 0; v = 0; } //确定随机数是否与之前生成的任何其他随机数不同并且与最后一个随机数不同 while(randomnumber === rotationArray[randomnumber] || randomnumber === lastnumber){ 随机数 = Math.floor(Math.random() * (quoteArray.length)); } lastnumber = 随机数; 旋转数组[随机数] = 随机数; ++v; //不相关的// //动画序列 $('#ctext, #cname').animate({'opacity':'0'},2000, function(){ $('#ctext').html(quoteArray[randomnumber].text); $('#cname').html('-' + quoteArray[randomnumber].cname); cHeight = $('#customerquotes').height() + 50; 调整高度(b高度,c高度,divtoanim); $('#ctext').delay(500).animate({'opacity':'1'},500); $('#cname').delay(1500).animate({'opacity':'1'},500); }); },15000);

【问题讨论】:

  • 什么是rotationArray,如何重置循环?
  • 你是如何声明这个数组的?
  • 直截了当地说,如果“quoteArray”没有用var quoteArray = [];var quoteArray = new Array(); 定义,那么它可能根本就不是一个数组。
  • rotationArray 是一个数组,存储每个循环产生的随机数。
  • quoteArray 声明如下: var quoteArray = new Array();

标签: javascript random while-loop infinite-loop


【解决方案1】:

这是一个异步问题:代码运行时数组quoteArray 为空,因为它触发了ajax 请求,然后继续。任何依赖于quoteArray 的东西都应该在$.ajaxsuccess 函数内。

当您在控制台中键入 quoteArray.length 时,数组有一个长度,只是因为到那时 Ajax 请求已经完成。

【讨论】:

  • 我不是在 firebug 中写“console.log(randomnumber)”,我只是在代码中内联写了它,所以每次它遍历 while 循环时,我都会读出“randomnumber”是什么.
  • @user 是的,即使这样。设置async: false 将导致浏览器阻止其他所有内容,但$.ajax 之后的脚本仍将运行。 async: false 通常不是你要找的。​​span>
  • @user,如果你把console.log(quoteArray.length);放在same循环中,你应该得到0
  • @box9 感谢您的澄清!我有错误的印象。我猜另一件事是a)这个函数直到页面加载后15秒才会运行,b)通过firebug查看ajax请求它们在运行之前都已经完成所以虽然我理解你的答案但我不明白它是如何应用的在这种情况下。
  • 另外值得注意的是:如果我一开始没有说清楚,这个脚本有时会成功运行(在 Chrome、Firefox 和 IE 中)。我似乎只在 Firefox 和 IE 中遇到了无限循环的问题,但在 Chrome 中没有。
【解决方案2】:

你有没有尝试过类似的东西

Math.floor(Math.random() * (5));

要确保正确找到数组长度?

【讨论】:

  • 我确信可以正确找到数组长度,因为我还使用了 console.log(quoteArray.length),它返回一个大于 0 的数字。quoteArray.length 将取决于数字函数循环的次数。
【解决方案3】:

首先,由于您更新了问题,请确保您正确处理异步数据。由于 ajax 调用是异步的,因此您需要确保仅在调用成功并返回数据后才运行随机发生器。

其次,假设您正在正确处理 asyc 数据,那么您的结果集的大小可能太小了。因此,您可能过于频繁地随机获得相同的数字。那么,你不能使用这个号码,因为你已经这样做了。

您需要做的是每次从结果数组中弹出已经使用的部分。重新计算数组长度,然后从中提取随机数。但是,这种感觉随机的可能性很小。

可能有一种更有效的方法来做到这一点,但这是我的尝试:

var results = ['some text','some text2','some text3','some text4','some text5', /* ...etc */ ],
       randomable = results;

function getRandomOffset( arr )
{
    var offset,
           len;

    if( arr.length < 1 )
        return false;
    else if( arr.length > 1 )
        offset = Math.floor(Math.random() * arr.length );
    else
        offset = 0;

    arr.splice( offset, 1 );

    return [
        offset,
        arr
    ];

}

while( res = getRandomOffset( randomable ) )
{
    // Set the randomable for next time
    randomable = res[1];
    // Do something with your resulting index
    results[ res[0] ];
}

发送给函数的arrgument 应该是从它返回的数组(第一次除外)。然后根据需要调用该函数,直到它返回 false。

【讨论】:

    猜你喜欢
    • 2019-07-27
    • 2021-03-22
    • 2014-04-30
    • 1970-01-01
    • 2014-05-07
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多