Javascript:Math.floor(Math.random()* array.length)不生成随机数?

时间:2011-03-10 19:37:52

标签: javascript random while-loop infinite-loop

这是一个doozey。

我有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之后,它会重置并重新开始循环。我遇到的问题是以下代码是SOMETIMES产生一个无限循环:

//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'。

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



编辑:这是包含函数+变量声明的完整相关代码


// Function to initialize the quoteObj
    function quoteObj(text,cname,ccompany,url,height) {
            this.text=text;
            this.cname=cname;
            this.ccompany=ccompany;
            this.url=url;
            this.height=height;
        }

// Populate my quotes Object with the quotation information from the XML sheet. 

    var qObj = new quoteObj('','','','');
    var quoteArray = new Array();
    var counter = 0;

//cycles through each XML item and loads the data into an object which is then stored in an array
    $.ajax({
        type: "GET",
        url: "quotes.xml",
        dataType: "xml",
        success: function(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();
                ++counter;
            });
        }
    });

// This is the setion that is generating my infinite loop issue.
// I've included all of the other code in case people are wondering specific things about how an item was initialized, etc. 

// Generate a random first quote then randomly progress through the entire set and start all over.      

    var randomnumber = Math.floor(Math.random() * (quoteArray.length));
    var rotationArray = new Array(quoteArray.length);
    var v = 0;
    var lastnumber = -1;

    bHeight = $('#rightbox').height() + 50;
    var cHeight = 0;
    var divtoanim = $('#customerquotes').parent();

//NOT RELATED// 
// Give the innershadow a height so that overflow hidden works with the quotations. 
    $(divtoanim).css({'height' : bHeight});

// Rotate the Quotations Randomly function. 
    setInterval(function(){     
        randomnumber = Math.floor(Math.random() * (quoteArray.length));

//checks to see if the function loop needs to start at the beginning. 
        if(v == (quoteArray.length)){
            rotationArray.length = 0;
            v = 0;
        }
//determines if the random number is both different than any other random number generated before and that is is not the same as the last random number
        while(randomnumber === rotationArray[randomnumber] || randomnumber === lastnumber){
            randomnumber = Math.floor(Math.random() * (quoteArray.length));
        }   

        lastnumber = randomnumber;
        rotationArray[randomnumber] = randomnumber;
        ++v;

//NOT RELATED//
//animation sequence
        $('#ctext, #cname').animate({'opacity':'0'},2000, function(){
            $('#ctext').html(quoteArray[randomnumber].text);
            $('#cname').html('- ' + quoteArray[randomnumber].cname);

            cHeight = $('#customerquotes').height() + 50;
            adjustHeight(bHeight,cHeight,divtoanim);

            $('#ctext').delay(500).animate({'opacity':'1'},500);
            $('#cname').delay(1500).animate({'opacity':'1'},500);
        });
    },15000); 

3 个答案:

答案 0 :(得分:2)

这是一个异步问题:代码运行时数组quoteArray为空,因为它会触发ajax请求,并继续。依赖于quoteArray的任何内容都应位于success的{​​{1}}函数内。

当您在控制台中键入$.ajax时,数组有一个长度,仅因为那时Ajax请求已完成。

答案 1 :(得分:0)

你试过像

这样的事吗?
Math.floor(Math.random() * (5));

确保正确找到阵列长度?

答案 2 :(得分:0)

首先,由于您更新了问题,请确保正确处理异步数据。由于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] ];
}

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