Javascript рандомизирует массив без элемента в начальной позиции

У меня проблема с джаваскриптом. У меня есть пользователь, который вводит список имен, которые я затем помещаю в массив. Короче говоря, я программирую случайный способ для людей выяснить, для кого они будут покупать рождественские подарки. Например, исходный массив состоит из следующих имен:

Alex
Joel
Lindsay
Cori

Затем я хочу рандомизировать имена, чтобы получить случайный список, подобный следующему:

Lindsay
Cori
Joel
Alex

Затем я бы отобразил имена из первого массива и выровнял их с рандомизированным именем в том же месте. Например, в этом примере Алекс связан с Линдси, Джоэл связан с Кори, Линдси связан с Джоэлом, а Кори связан с Алексом. В настоящее время я использую следующий метод рандомизации:

function shuffle(array){
    var m = array.length, t, i;
    while(m){
        i = Math.floor(Math.random() * m--);
        t = array[m];
        array[m] = array[i];
        array[i] = t;
    }
    return array;
};

Проблема с этой функцией заключается в том, что массив не рандомизируется в новое место. Например, с помощью этого метода я могу иметь следующий исходный массив:

Alex
Joel
Lindsay
Cori

И мой массив с приведенной выше функцией для его рандомизации приведет к чему-то вроде этого:

Cori
Alex
Lindsay
Joel

Это означает, что Алекс связан с Кори, Джоэл связан с Алексом, Линдси связан с Линдси, а Кори связан с Джоэлом. Вот в чем проблема. Если это программа, чтобы узнать, кто кому покупает рождественский подарок, Линдси НЕ может купить подарок для Линдси.

Какой будет подходящая функция рандомизации массива для решения этой проблемы?

Спасибо за помощь!!


person Alex Neises    schedule 16.12.2013    source источник
comment
Почему бы вам не добавить проверки, чтобы одинаковые имена не совпадали? Это больше не становится случайным, но похоже на то, что вы ищете   -  person A Person    schedule 16.12.2013
comment
Как именно я буду это делать? У меня была функция if в цикле for, в которой говорилось, что если имена равны, то я снова вызову функцию. Это, однако, не включало все имена, и это не казалось лучшим решением.   -  person Alex Neises    schedule 16.12.2013
comment
Вместо перетасовки вы можете найти случайное имя для каждого имени. и каждый раз удаляя найденное имя и текущее имя из доступного для поиска массива   -  person jonasnas    schedule 16.12.2013


Ответы (2)


Попробуйте --m, а не m--:

function shuffle(array){
    var m = array.length, t, i;
    while(m){
        i = Math.floor(Math.random() * --m);
        t = array[m];
        array[m] = array[i];
        array[i] = t;
    }
    return array;
};

Потому что, если вы используете m--, вы можете получить i == m и поменять местами элемент массива с самим собой.

person Tony    schedule 16.12.2013
comment
Не думал, что это такое простое решение. Благодарю вас! - person Alex Neises; 16.12.2013
comment
Я только что понял, что ты прав... \o/. Извиняюсь. - person Pedro Moreira; 16.12.2013
comment
@Pedro Все в порядке, я был готов это обсудить :) - person Tony; 16.12.2013

Сначала я построил массив индексов, затем перетасовал его и проверил окончательное застревание.

Я думаю, это то, что вы хотите: (я добавил галочку в конце, не забудьте удалить ее)

<script>
    var start = [ 'Alex', 'Joel', 'Lindsay', 'Cori' ]

    function shuffle(array) {
        // Support
        var support = [];
        for(var i = 0; i < array.length; i++) {
            support[i] = i;
        }

        // Support Build
        for(var i = 0; i < support.length; i++) {
            var random = Math.floor(Math.random() * (support.length - i)) + i;

            if(i == (support.length - 2) && support[i + 1] == (i + 1)) {
                var ex = support[i];
                support[i] = support[i + 1];
                support[i + 1] = ex;
                break;
            }

            if(random == support[i]) {
                i--;
                continue;
            }

            var ex = support[i];
            support[i] = support[random];
            support[random] = ex;
        }

        // Result
        var result = [];
        for(var i = 0; i < support.length; i++) {
            result[i] = array[support[i]];
        }

        return result;
    };

    for(var i = 0; i < 1000; i++) {
        if(start == shuffle(start))
            alert('fail.');
    }
</script>
person Pedro Moreira    schedule 16.12.2013