我是一名新手程序员,并为这个复杂的问题道歉。
我正在尝试为实验研究创建一个词汇决策任务,其中受访者必须决定屏幕上显示的一系列字母是“单词”还是“非单词”。除了我想从一个单独的输入文件(input.txt)为80个试验中的每一个随机选择一个单词(A类)或非单词(B类)的位之外,一切都运行得相当好。随机化有效,但每个列表(类别A或B)中的一些元素被跳过,因为我使用了“round.catIndex = j;”其中“j”是每次连续试验的循环。由于某些试验是从A类中随机选择而从B类中随机选择的,因此“j”不会在每个类别的列表中连续移动。相反,类别A列表中的元素可以从1,2,5,8,9,10等中选择(由于随机化,它每次都会变化)。
长话短说(!),如何创建一个在每个试验的for-loop中工作的计数器,这样分别来自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;
}
答案 0 :(得分:0)
您可以使用comma operator声明多个变量并在单个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++)
类型的循环。
如果后者是您真正想要的,请对此答案发表评论,我将使用其他示例进行更新。
修改强>
好吧,我假设你的测试并没有真正定义单词和非单词的实际数量和顺序,因为否则用户可以选择单词/非单词模式和圣诞树进行测试。我还假设你在全局范围内有两个单词和非单词数组catA
和catB
。以下是将执行以下操作的功能:
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
函数需要跟踪三个变量:{{1}的副本}和catA
,以及与catB
大小相同的数组,其中一半是numrounds
,另一半是true
。从此true / false数组中随机false
,然后从splice
或catA
随机拼接,具体取决于它是catB
还是true
。那么你的函数将需要代码来“刷新”所有这些闭包变量,但它与上面编写函数的方式基本相同。
很抱歉,如果该功能有点复杂,但您看到使用起来有多容易,对吧? :)
答案 1 :(得分:0)
我不完全确定我理解你的问题。以下是基于您对问题的可能解释的答案:
您希望使用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)
如果这不是您的意图,请澄清。