简体   繁体   English

在循环内创建计数器?

[英]Create a Counter within a For-Loop?

I am a novice programmer and apologize upfront for the complicated question. 我是一个新手程序员,对于这个复杂的问题预先表示歉意。

I am trying to create a lexical decision task for experimental research, in which respondents must decide if a series of letters presented on the screen make a "word" or "not a word". 我正在尝试为实验研究创建词汇决策任务,在该任务中,受访者必须确定屏幕上显示的一系列字母是“单词”还是“不是单词”。 Everything works reasonably well except for the bit where I want to randomly select a word (category A) or nonword (category B) for each of 80 trials from a separate input file (input.txt). 除了我想从单独的输入文件(input.txt)中为80个试验中的每一个随机选择一个单词(A类)或一个非单词(B类)之外,其他所有内容都运行良好。 The randomization works, but some elements from each list (category A or B) are skipped because I have used "round.catIndex = j;" 随机化是可行的,但是由于我使用了“ round.catIndex = j;”,所以跳过了每个列表(A类或B类)中的某些元素。 where "j" is a loop for each successive trial. 其中“ j”是每个连续试验的循环。 Because some trials randomly select from Category A and other from Category B, "j" does not move successively down the list for each category. 因为某些试验从A类中随机选择,其他试验从B类中随机选择,所以“ j”不会在每个类别的列表中连续向下移动。 Instead, elements from the Category A list may be selected from something like 1, 2, 5, 8, 9, 10, and so on (it varies each time because of the randomization). 取而代之的是,可以从类别1、2、5、8、9、10等中选择类别A列表中的元素(由于随机化,它每次都会变化)。

To make a long story short(!), how do I create a counter that will work within the for-loop for each trial, so that every word and nonword from Category A and B, respectively, will be used for the lexical decision task? 长话短说(!),我如何创建一个在每次试验的for循环中都可以使用的计数器,以便将类别A和B中的每个单词和非单词分别用于词汇决策任务? Everything I have tried thus far does not work properly or breaks the javascript entirely. 到目前为止,我尝试过的所有操作均无法正常运行或完全破坏了javascript。

Below is my code snippet and the full code is available at http://50.17.194.59/LDT/trunk/LDT.js . 以下是我的代码段,完整的代码位于http://50.17.194.59/LDT/trunk/LDT.js Also, the full lexical decision task can be accessed at http://50.17.194.59/LDT/trunk/LDT.php . 另外,可以在http://50.17.194.59/LDT/trunk/LDT.php上访问完整的词汇决策任务。 Thanks! 谢谢!

    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;
    }

You can use the comma operator to declare multiple variables and execute multiple statements within a single for loop. 您可以使用逗号运算符在单个for循环中声明多个变量并执行多个语句。

In your case, you could do something like: 就您而言,您可以执行以下操作:

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

I chose those verbose variable names to make it more clear. 我选择了这些冗长的变量名称,以使其更清楚。 You'd have two separate indices for category A and B, and you compare the sum of the two versus the number of rounds you want to run. 对于类别A和类别B,您将有两个单独的索引,然后将两者的总和与要运行的回合数进行比较。 Then inside of your for loop somewhere, you set the boolean incrementA to either true or false to indicate which one to increment. 然后在for循环中的某个地方,将布尔值incrementA设置为truefalse以指示要递增的值。

That roughly matches what you're asking for, but I think what you'd prefer is to use a combination of Math.random , <array>.splice and <array>.length to get a random word/nonword from each list, rather than producing a predictable order for selection. 这大致符合您的要求,但我认为您更喜欢使用Math.random<array>.splice<array>.length的组合,从每个列表中获取随机单词/非单词,而不是产生可预测的选择顺序。 Then you don't even care what the indices are for the two categories and you can go back to a simple for(var i = 0; i < numrounds; i++) type of loop. 然后,您甚至不必关心这两个类别的索引是什么,并且可以返回到简单的for(var i = 0; i < numrounds; i++)类型的循环。

If the latter is what you really want, leave a comment on this answer and I'll update it with another example. 如果后者是您真正想要的,请在此答案上留下评论,我将用另一个示例对其进行更新。

EDIT: 编辑:

Okay, I'm assuming that the actual number and order of words and non-words is not really defined by your test, because otherwise a user could pick up the word/non-word pattern and Christmas Tree the test. 好的,我假设您的测试并未真正定义单词和非单词的实际数量和顺序,因为否则用户可以选择单词/非单词模式并在圣诞树上进行测试。 I'm also assuming that you have two array of words and non-words called catA and catB in the global scope. 我还假设您在全局范围内有两个单词和非单词数组,分别称为catAcatB Below is a function that will do the following: 以下是将执行以下操作的函数:

  1. Randomly pick a word or non-word. 随机选择一个单词或一个非单词。
  2. Never repeat a word or non-word pick (meaning that technically it becomes more deterministic the closer to the end of the list you are. 永远不要重复单词或非单词选择(从技术上讲,这意味着您越靠近列表的末尾,它就越具有确定性。
  3. Until all words are exhausted, at which point it will automatically "refresh" its list from the catA and catB arrays. 直到所有单词都用尽为止,这时它将自动从catAcatB数组中“刷新”其列表。 (So you can set numrounds to +inf if you like.) (因此,您可以根据需要将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];
    };
})();

The function is using the functional programming concept of closures to create a persisted "global-like" variable, allWords that only it can see. 该函数使用闭包的函数编程概念来创建一个持久的“全局变量”变量,只有它才能看到的allWords The function automatically refreshes the array with all of the words when the length of the array reaches zero (like it is from the start) using the globals catA and catB . 当数组的长度达到零时(就像从头开始一样),该catA使用全局变量catAcatB自动刷新所有单词。 To use it in a for loop, simply: 要在for循环中使用它,只需:

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

If you need to guarantee that an equal number of catA and catB words are used, the outerScope function will need to keep track of three variables: copies of catA and catB , and an array the same size as numrounds , half of which are true and half false . 如果你需要保证相同数量的catAcatB使用的话,则outerScope功能将需要保持三个变量的轨迹:拷贝catAcatB和数组的大小相同numrounds ,其中一半是true ,并半false splice randomly from this true/false array, and then splice randomly from either catA or catB depending on whether it's true or false . splice从该真/假随机阵列,然后随机从任一拼接catAcatB取决于它是否是truefalse Then you function will need code to "refresh" all of these closure variables, but it would be essentially the same as how the function is written above. 然后,您的函数将需要代码来“刷新”所有这些闭包变量,但是它与上面的函数基本相同。

Sorry if the function is a bit complex, but you see how easy it is to use, right? 抱歉,如果函数有点复杂,但是您会发现它的使用非常简单,对吧? :) :)

I'm not entirely sure I understand your problem. 我不确定我是否理解您的问题。 Here is my answer based on this possible interpretations of your question: 这是根据您对问题的可能解释得出的我的答案:

You would like to use a for loop to process all of the Category A elements (and similarly another loop to process all Category B elements). 您想使用一个for循环来处理所有的Category A元素(类似地,另一个循环来处理所有的Category B元素)。 In this case you can loop through the roundArray and treat the elements according to their category: 在这种情况下,您可以遍历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)

If this is not your intention, please clarify. 如果这不是您的意图,请进行说明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM