Javascript: Math.floor (Math.random () * array.length) не производит случайное число? - PullRequest
1 голос
/ 10 марта 2011

Это на е-дузи.

У меня есть цикл 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 ]

2 голосов
/ 11 марта 2011

Это асинхронная проблема: массив quoteArray пуст во время выполнения кода, потому что он запускает запрос ajax и перемещается на .Все, что зависит от quoteArray, должно быть внутри функции success $.ajax.

Массив имеет длину при вводе quoteArray.length в консоли, только потому, что byв этот раз запрос Ajax завершился.

0 голосов
/ 10 марта 2011

Во-первых, поскольку вы обновили свой вопрос, убедитесь, что вы правильно обрабатываете асинхронные данные.Поскольку вызов ajax является асинхронным, вам нужно будет обязательно запускать рандомизатор только после успешного вызова и получения данных.

Во-вторых, при условии, что вы обрабатываете асинхронные данные должным образом, размер вашегоНабор результатов, вероятно, слишком мал.Таким образом, вы, вероятно, случайно получаете одно и то же число слишком часто.Тогда вы не можете использовать этот номер, потому что вы уже сделали это.

Что вам нужно сделать, это выскочить из частей, которые уже используются из массива результатов каждый раз.Пересчитайте длину массива, затем вытащите случайную величину из этого.Однако вероятность этого случайного чувства очень мала.

Вероятно, есть более эффективный способ сделать это, но вот мой путь:

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, отправленнаяфункция должна быть массивом, который возвращается из нее (кроме первого раза).Затем вызывайте эту функцию по мере необходимости, пока она не вернет false.

0 голосов
/ 10 марта 2011

вы пробовали что-то вроде

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

Чтобы убедиться, что длина массива найдена правильно?

...