Создать счетчик внутри цикла? - PullRequest
0 голосов
/ 21 марта 2012

Я начинающий программист и заранее прошу прощения за сложный вопрос.

Я пытаюсь создать задачу лексического решения для экспериментального исследования, в котором респонденты должны решить, составляют ли серии букв, представленных на экране,«слово» или «не слово».Все работает достаточно хорошо, за исключением бита, в котором я хочу случайным образом выбрать слово (категория A) или неслово (категория B) для каждого из 80 испытаний из отдельного входного файла (input.txt).Рандомизация работает, но некоторые элементы из каждого списка (категории A или B) пропускаются, потому что я использовал "round.catIndex = j;"где «j» - цикл для каждого последующего испытания.Поскольку некоторые испытания случайным образом выбираются из категории A, а другие - из категории B, «j» не перемещается последовательно вниз по списку для каждой категории.Вместо этого элементы из списка категории А могут быть выбраны из чего-то вроде 1, 2, 5, 8, 9, 10 и т. Д. (Это меняется каждый раз из-за рандомизации).

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

Ниже приведен мой фрагмент кода, а полный код доступен по адресу http://50.17.194.59/LDT/trunk/LDT.js. Также доступна полная задача лексического решения.http://50.17.194.59/LDT/trunk/LDT.php. Спасибо!

    function initRounds()
    {
        numlst = [];
        for (var k = 0; k<numrounds; k++)
            {
                if (k % 2 == 0) numlst[k] = 0;
                else numlst[k] = 1;
            }
        numlst.sort(function() {return 0.5 - Math.random()})

        for (var j = 0; j<numrounds; j++)
            {       
                var round = new LDTround();
                if (numlst[j] == 0)
                    {
                        round.category = input.catA.datalabel;
                    }
                else if (numlst[j] == 1)
                    {
                        round.category = input.catB.datalabel;
                    }

                // pick a category & stimulus
                    if (round.category == input.catA.datalabel) 
                        {
                            round.itemtype = input.catA.itemtype;
                            round.correct = 1;
                            round.catIndex = j;
                        }
                    else if (round.category == input.catB.datalabel)
                        { 
                            round.itemtype = input.catB.itemtype;
                            round.correct = 2;
                            round.catIndex = j;   
                        }       
                    roundArray[i].push(round);
                }
        return roundArray;
    }

Ответы [ 2 ]

0 голосов
/ 21 марта 2012

Я не совсем уверен, что понимаю вашу проблему.Вот мой ответ, основанный на этой возможной интерпретации вашего вопроса:

Вы хотели бы использовать цикл for для обработки всех элементов категории A (и аналогично другой цикл для обработки всех элементов категории B).В этом случае вы можете циклически проходить по массиву roundArray и обрабатывать элементы в соответствии с их категорией:

for (var j=0; j < numrounds, j++) {
  var round = roundArray[i][j];
  // you might want to use a test better suiting the context if input is not available at the
  // time when round is processed, I am using this based on the code sample you provided
  if (round.itemType == input.catA.itemType) {
    // process round as Category A
    // use numlst[round.catIndex] to access the corresponding element in numlst
  } else {
    // process round as Category B
    // use numlst[round.catIndex] to access the corresponding element in numlst
  }
}
// alternatively, you can break the loop into two and process only Category A in one instance
// and only Category B in the other (the if branch corresponding to the other category would be
// empty)

Если это не ваше намерение, уточните.

0 голосов
/ 21 марта 2012

Вы можете использовать оператор запятой для объявления нескольких переменных и выполнения нескольких операторов в одном цикле for.

В вашем случае вы можете сделать что-то вроде:

for(var CatAIndex = 0, CatBIndex = 0; CatAIndex+CatBIndex < numrounds; incrementA ? CatAIndex++ : CatBIndex++) {
    // Insert your code here
}

Я выбрал эти подробные имена переменных, чтобы сделать их более понятными. У вас будет два отдельных индекса для категорий A и B, и вы сравните сумму двух с количеством раундов, которые вы хотите запустить. Затем внутри своего цикла for вы устанавливаете логическое значение incrementA либо true, либо false, чтобы указать, какой из них увеличить.

Это примерно соответствует тому, что вы просите, но я думаю, что вы бы предпочли использовать комбинацию Math.random, <array>.splice и <array>.length, чтобы получить случайное слово / неслово из каждого списка, скорее чем производить предсказуемый порядок выбора. Тогда вам даже не нужно заботиться , каковы индексы для этих двух категорий, и вы можете вернуться к простому типу цикла for(var i = 0; i < numrounds; i++).

Если последнее действительно то, что вам нужно, оставьте комментарий к этому ответу, и я обновлю его другим примером.

EDIT:

Хорошо, я предполагаю, что фактическое количество и порядок слов и неслов на самом деле не определены вашим тестом, потому что в противном случае пользователь мог бы подобрать шаблон слова / неслова и рождественскую елку. Я также предполагаю, что у вас есть два массива слов и не-слов с именами catA и catB в глобальной области видимости. Ниже приведена функция, которая будет выполнять следующие действия:

  1. Случайно выбрать слово или не слово.
  2. Никогда не повторяйте выбор слова или неслова (это означает, что технически он становится более детерминированным, чем ближе к концу списка вы находитесь.
  3. Пока все слова не будут исчерпаны, в этот момент он автоматически "обновит" свой список из массивов catA и catB. (Так что вы можете установить numrounds на +inf, если хотите.)

.

var pickAWord = (function outerScope() {
    var allWords = [];
    return function innerClosure() {
        if(allWords.length == 0) {
            allWords = [].concat(catA, catB);
        }
        return allWords.splice(Math.floor(Math.random()*allWords.length), 1)[0];
    };
})();

Функция использует концепцию замыканий функционального программирования для создания постоянной «глобальной» переменной allWords, которую может видеть только она. Функция автоматически обновляет массив со всеми словами, когда длина массива достигает нуля (как и в начале), используя глобалы catA и catB. Чтобы использовать его в цикле for, просто:

for(var i = 0; i < numrounds; i++) {
    var wordToUse = pickAWord();
    // Do something
}

Если вам нужно гарантировать, что используется одинаковое количество слов catA и catB, функция outerScope должна будет отслеживать три переменные: копии catA и catB и массив такого же размера, как numrounds, половина из которых true и половина false. splice случайным образом из этого массива true / false, а затем случайным образом сращивается из catA или catB в зависимости от того, true или false. Тогда вам понадобится код, чтобы «обновить» все эти переменные замыкания, но он по сути будет таким же, как написано выше.

Извините, если функция немного сложна, но вы видите, как легко ее использовать, верно? :)

...