我是一个新手程序员,并为这个复杂的问题提前道歉。
我正在尝试为实验研究创建一个词汇判断任务,在这个任务中,受访者必须判断屏幕上出现的一系列字母是“单词”还是“不是单词”。除了我想从一个单独的输入文件(input.txt)中为80个试验中的每个试验随机选择一个词(A类)或非词(B类)之外,一切都运行得相当好。随机化是有效的,但是每个列表(类别A或B)中的一些元素被跳过,因为我使用了"round.catIndex = j;“,其中"j”是每个后续试验的循环。因为一些试验是从类别A中随机选择的,而其他试验是从类别B中随机选择的,所以"j“不会在每个类别的列表中连续向下移动。相反,Category A列表中的元素可能是从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;
}发布于 2012-03-21 07:25:04
您可以使用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函数将需要跟踪三个变量:catA和catB的副本,以及一个与numrounds大小相同的数组,其中一半是true,另一半是false。从这个真/假数组中随机拼接,然后从catA或catB中随机拼接,这取决于它是true还是false。然后,您的函数将需要代码来“刷新”所有这些闭包变量,但它本质上与上面编写函数的方式相同。
如果函数有点复杂,很抱歉,但您可以看到它有多容易使用,对吧?:)
发布于 2012-03-21 22:16:33
我不确定我是否完全理解你的问题。以下是我基于对你的问题的可能解释的答案:
您希望使用一个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)如果这不是你的意图,请澄清。
https://stackoverflow.com/questions/9795018
复制相似问题