альтернативы для чрезмерного цикла () в JavaScript - PullRequest
1 голос
/ 26 июня 2011

Положение

В настоящее время я пишу виджет JavaScript, который отображает случайные кавычки в элемент HTML. цитаты хранятся в массиве javascript, а также сколько раз они отображались в элементе html. Отображаемая цитата не может быть той же самой цитатой, которая была ранее отображена. Кроме того, вероятность выбора цитаты основана на ее предыдущих вхождениях в элементе html. (меньшее количество случаев должно привести к более высокой вероятности по сравнению с другими цитатами, которые будут выбраны для отображения.

Текущее решение

В настоящее время я заставил это работать (с моими крайними недостатками в знании javascript), используя множество циклических циклов по различным массивам. хотя в настоящее время это работает (!!), я считаю, что это решение довольно дорого для того, чего я хочу достичь.

Что я ищу

  • Альтернативные методы удаления элемента массива из массива , в настоящее время цикл по всему массиву для поиска элемента, который я хочу удалить, и копирование всех других элементов в новый массив
  • Альтернативный метод вычисления и выбора элемента из массива по его появлению
  • Все остальное, что вы заметили, я должен / мог бы сделать по-другому, все еще применяя установленные бизнес-правила согласно Ситуация

Код

var quoteElement = $("div#Quotes > q"),
    quotes = [[" AAAAAAAAAAAA ", 1],
              [" BBBBBBBBBBBB ", 1],
              [" CCCCCCCCCCCC ", 1],
              [" DDDDDDDDDDDD ", 1]],
    fadeTimer = 600,
    displayNewQuote = function () {

                        var currentQuote = quoteElement.text();
                        var eligibleQuotes = new Array();
                        var exclusionFound = false;
                        for (var i = 0; i < quotes.length; i++) {
                            var iteratedQuote = quotes[i];
                            if (exclusionFound === false) {
                                if (currentQuote == iteratedQuote[0].toString())
                                    exclusionFound = true;
                                else
                                    eligibleQuotes.push(iteratedQuote);
                            } else
                                eligibleQuotes.push(iteratedQuote);
                        }
                        eligibleQuotes.sort( function (current, next) {
                            return current[1] - next[1];
                        } );

                        var calculatePoint = eligibleQuotes[0][1];
                        var occurenceRelation = new Array();
                        var relationSum = 0;
                        for (var i = 0; i < eligibleQuotes.length; i++) {
                            if (i == 0)
                                occurenceRelation[i] = 1 / ((calculatePoint / calculatePoint) + (calculatePoint / eligibleQuotes[i+1][1]));
                            else
                                occurenceRelation[i] = occurenceRelation[0] * (calculatePoint / eligibleQuotes[i][1]);
                            relationSum = relationSum + (occurenceRelation[i] * 100);
                        }

                        var generatedNumber = Math.floor(relationSum * Math.random());
                        var newQuote;
                        for (var i = 0; i < occurenceRelation.length; i++) {
                            if (occurenceRelation[i] <= generatedNumber) {
                                newQuote = eligibleQuotes[i][0].toString();
                                i = occurenceRelation.length;
                            }
                        }

                        for (var i = 0; i < quotes.length; i++) {
                            var iteratedQuote = quotes[i][0].toString();
                            if (iteratedQuote == newQuote) {
                                quotes[i][1]++;
                                i = quotes.length;
                            }
                        }

                        quoteElement.stop(true, true)
                                    .fadeOut(fadeTimer);
                        setTimeout( function () {
                            quoteElement.html(newQuote)
                                        .fadeIn(fadeTimer);
                        }, fadeTimer);

                    } 

if (quotes.length > 1) 
    setInterval(displayNewQuote, 10000);

Рассмотрены альтернативы

  • Всегда выбирал элемент массива с наименьшим вхождением.

    Принято решение об этом, поскольку это может / могло бы выявить слишком очевидную закономерность в анимации

  • объединить несколько циклов для уменьшения рабочей нагрузки

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

jsFiddle reference

http://jsfiddle.net/P5rk3/

Обновление

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

Список использованных ссылок после прочтения ответов здесь:

Ответы [ 5 ]

3 голосов
/ 26 июня 2011

Я предлагаю функции массива, которые в основном поддерживаются (и легко добавляются, если нет):

[].splice(index, howManyToDelete); // you can alternatively add extra parameters to slot into the place of deletion
[].indexOf(elementToSearchFor);
[].filter(function(){});

Другие полезные функции включают forEach и map.

Я согласен, что объединениевся работа в одном гигантском цикле безобразна (и не всегда возможна), и вы мало выигрываете, делая читабельность, безусловно, победителем.Хотя вам не нужно слишком много циклов с этими функциями массива.

2 голосов
/ 26 июня 2011

Ответ, который вы хотите:

Создание целочисленного массива, в котором хранится количество использований каждой цитаты. Кроме того, глобальная переменная Tot с общим количеством уже использованных кавычек (т.е. сумма этого целочисленного массива). Найдите также Mean, как Tot / number of quotes.

Выберите случайное число от 0 до Tot - 1.

Для каждой цитаты добавьте Mean * 2 - the number of uses (* 1). Когда вы получите, что это значение превысило сгенерированное случайное число, выберите эту кавычку.

В случае, если эта кавычка отображается в данный момент, выберите следующую или предыдущую кавычку или просто повторите процесс.

Реальный ответ:

Используйте случайную цитату, при максимальном повторении, если цитата дублируется. Использование данных будет потеряно, когда пользователь перезагрузит / покинет страницу. И как бы умно вы их ни выбрали, большинству пользователей все равно.

(* 1) Проверьте лимиты, т. Е. Первая или последняя квота будут соответствовать этой формуле.

1 голос
/ 26 июня 2011

Альтернативные методы удаления элемента массива из массива

С ES5's Array.filter() метод:

Array.prototype.without = function(v) {
    return this.filter(function(x) {
        return v !== x;
    });
};

при наличии массива a, a.without(v) вернет копию a без элемента v.

меньшее количество случаев должно привести к увеличению вероятностипо сравнению с другими кавычками, которые будут выбраны для отображения

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

То, что вы предлагаете, сродни идее, что числа в лотерее, которые еще не выпали, должны быть "запоздалыми" и, следовательно, более вероятными.Это просто неправда.

0 голосов
/ 26 июня 2011

Если по каким-то причинам вам не удобны методы splice или filter, есть хороший (устаревший, но все еще работающий) метод Джона Резига: http://ejohn.org/blog/javascript-array-remove/

0 голосов
/ 26 июня 2011

Вы можете написать функции, которые явно определяют, что вы пытаетесь делать с циклом.

Ваш первый цикл - filter .Ваш второй цикл - карта + некоторый побочный эффект.Я не знаю о других циклах, они странные: P

Фильтр - это что-то вроде:

function filter(array, condition) {
    var i = 0, new_array = [];
    for (; i < array.length; i += 1) {
        if (condition(array[i], i)) {
            new_array.push(array[i]);
        }
    }
    return new_array;
}

var numbers = [1,2,3,4,5,6,7,8,9];
var even_numbers = filter(numbers, function (number, index) {
    return number % 2 === 0;
});
alert(even_numbers); // [2,4,6,8]

Вы не можете избежать цикла, но вы можете добавить семантику к коду, сделав функцию, объясняющую, что вы делаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...