Create a Counter within a For-Loop? - php

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). The randomization works, but some elements from each list (category A or B) are skipped because I have used "round.catIndex = j;" where "j" is a loop for each successive trial. Because some trials randomly select from Category A and other from Category B, "j" does not move successively down the list for each category. 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).
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? Everything I have tried thus far does not work properly or breaks the javascript entirely.
Below is my code snippet and the full code is available at 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. 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.
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. Then inside of your for loop somewhere, you set the boolean incrementA to either true or false to indicate which one to increment.
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. 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.
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. Below is a function that will do the following:
Randomly pick a word or non-word.
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.
Until all words are exhausted, at which point it will automatically "refresh" its list from the catA and catB arrays. (So you can set numrounds to +inf if you like.)
.
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. 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. To use it in a for loop, simply:
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. splice randomly from this true/false array, and then splice randomly from either catA or catB depending on whether it's true or false. 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). In this case you can loop through the roundArray and treat the elements according to their category:
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.

Related

I need a program in PHP, where I search a number in a series mentioned and then give output as the index on which it is present?

I need a program in PHP, when I search a number in a given series like 1,3,7,15,31... and if it is present in the series then give output as the index on which it is present in series?
LIKE I HAVE DONE SOMETHING TO DO THIS BUT FAILED.
<?php
function test1($n) {
for($i=1;$i<=$n;$i=$c) {
$c =1 + (2 * $i);
}
}
function test2($p) {
global $c,$n;
$input=array(1);
$in=array_push($input,$c);
$k=array_search($p,$input);
$flipped = array_flip($k);
var_dump($flipped);
}
test1(1000000);
test2(45);
Like in this program I had made two functions and in FUNCTION test1 I made a formula to make the series 1,3,7,15,31,63,127.... and in FUNCTION test2 I insert a number in form of parameter and want to SEARCH that number in the series that I form above and the I want OUTPUT as the index of that number searched.
Also if the number is not present in the series then I want the output as the nearest number of the number I search.
HELP.!!!
Thank You
You've got a few problems with this code.
function test1($n) {
for($i=1;$i<=$n;$i=$c) {
$c =1 + (2 * $i);
}
}
The first problem here is that you don't do anything with $c each time you increment it. You should probably be pushing it into an array of series integers.
Secondly you don't return a result, so you can't actually use the series you would've created.
You could use something like this instead:
function test1($limit) {
$series = [];
for ($i = 1; $i <= $limit; $i = $i * 2 + 1) {
$series[] = $i;
}
return $series;
}
Next, your test2 function:
function test2($p) {
global $c,$n;
$input=array(1);
$in=array_push($input,$c);
$k=array_search($p,$input);
$flipped = array_flip($k);
var_dump($flipped);
}
Ok, first don't use global variables. Pass the ones you need in as arguments and again, return the result. To be perfectly honest, I'm not entirely sure what this function is supposed to do. All you need is the array_search call which "searches the array for a given value and returns the first corresponding key if successful".
For example:
function test2($series, $number) {
return array_search($number, $series);
}
Using these, you can do something like this:
$series = test1(1000000);
var_dump(test2($series, 45)); // bool(false)
var_dump(test2($series, 31)); // int(4)
Also if the number is not present in the series then I want the output as the nearest number of the number I search.
Ok, you'll need to write some custom logic for this. I suggest you run your array_search check, then if it returns false you loop through your series and check the following criteria:
The previous series entry is lower than your number
The next series entry is higher than your number
Then return whichever of those two has a smaller absolute difference when you subtract the series entry from your number.
I'm not going to write an example for this because it smells a bit like a school assignment, which I'm sure you're capable of doing =) good luck.

Should calculations be repeated in if statements?

If a calculation is used in the evaluation expression of an if statement and then again in the execution statement(s), is it more or less efficient to perform the calculation twice or to introduce a new variable?
In other words, is
if ($x <> some_complex_calculation()) {
...
$x = some_complex_calculation();
}
better than this:
$result = some_complex_calculation();
if ($x <> $result) {
...
$x = $result;
}
Or, is this:
if ($x <> get_something_from_database()) {
...
$x = get_something_from_database();
}
better than this:
$result = get_something_from_database();
if ($x <> $result) {
...
$x = $result;
}
Of course it will always be more efficient to save the results of the calculation, no matter how trivial it may be, so if that is all you care about using a temporary is the only "correct" option.
That said, the performance aspect would only be important if the calculation takes up a sizeable amount of your total running time, which is unusual in practice. On the other hand, there are other considerations that can influence or even dictate your decision:
Correctness: If you do the calculation twice there is the possibility that the application state will have changed between the two calculations. So you would enter a branch because e.g. get_something() > 5 but then inside the branch it could be that get_something() <= 5 because someone else has modified the data in the meantime. Does it matter to you? How do you want the app to behave in this case? These are questions far more important than "is it going to run faster".
Understandability: Whenever I see a variable being defined, I usually have to allocate a "mental slot" to tracking that variable and its usages until I have figured out how the function it is defined in works as a whole. If the code is using too many temporaries then the cognitive load to the reader is increased. Does it matter to you? What is the relative impact vs the performance difference?
If the calculation has different arguments at each call and thus different results, then you will need to call it each time. For example:
function add( a, b )
{
return a + b;
}
And called like so:
if( add( 1, 2) > a )
else if ( add( 4,5 ) > c )
This would return different values each time so you would need to compute it in the if.
However if it is the same comparison value each time, it better to store the result if used more than once:
result = add(5, 6)
if( result > 10 )
else if( result > 12 )

Local/Global vars in PHP

I'm a newb. I have several tables to store forms and I want the next user's input to be stored the table with the least responses (each form is different).
I've taken the rowcounts from the sql db and they are working. I use the code below detect how many responses there are and hence set $testnumber accordingly.
The code fails. Essentially, when I echo $testnumber, it doesn't matter what values the row counts are, it just randomises according to the first if statement.
When I delete the first if statement, I get an error saying that $testnumber is undefined regardless of the values of rowcounts.
I am absolutely confused the hell out. In my head the var $testnumber is local in all of the statements (they are not defined elsewhere) so they should all either work or not work.
I would appreciate some help. I know my if statements are crap and doesn't cover all cases so any help here would be useful but most IMPORTANTLY can you explain why my other statements are being ignored and why the first one isnt?
Thank you
if ($rowcount1 = $rowcount2 = $rowcount3 = $rowcount4){ // if all rowcounts are equal
$testnumber = mt_rand(1,4);
}
if ($rowcount1 < $rowcount2){ //rowcount for 1 is lowest
if($rowcount1 < $rowcount3){
if($rowcount1 < $rowcount4){
$testnumber = 1;
}
}
};
if ($rowcount2 < $rowcount1){ // rowcount for 2 is lowest
if($rowcount2 < $rowcount3){
if($rowcount2 < $rowcount4){
$testnumber = 2;
}
}
};
if ($rowcount3 < $rowcount1){ // rowcount for 3 is lowest
if($rowcount3 < $rowcount2){
if($rowcount3 < $rowcount4){
$testnumber = 3;
}
}
};
if ($rowcount4 < $rowcount1){ //rowcount for exp2 is lowest
if ($rowcount4 < $rowcount2){
if ($rowcount4 < $rowcount3){
$testnumber = 4;
}
}
};
echo "Final Testnumber: " . $testnumber;
Your first comparison statement isn't a comparison at all: single = sets a variable, double == tests for equality. Thus, your conditional will always evaluate to TRUE, because it's setting your variables correctly.
On top of that, you need to expand out your statements, as equality comparisons don't work this way in PHP.
if (($rowcount1 == $rowcount2) && ($rowcount2 == $rowcount3) && ($rowcount3 == $rowcount4)){ // if all rowcounts are actaully equal
Check out the relevant PHP docs: Assignment Operators, Comparison Operators
Edit: Your next conditional statements are hampered by the fact that it appears you're running into issues with Variable Scope. Basically, in order to access the $testnumber variable, you'll need to define it outside the "scope" of a conditional block.
$testnumber = 0;
if (($rowcount1 == ...
While outside the scope of the question: based on what you've provided here, it may be worthwhile to check out the PHP documentation on arrays, it will help you immensely as you start to scale your code up.

PHP: If condition with explode within foreach loop

I am trying to get multiple value from user input from text field and want to explode or keep adding into if condition statement
Here is my code
foreach ($list['post'] as $item) {
if( ($item['single']['catid'] != 8) AND ($item['single']['catid'] != 4) ){
$this->list_post($item);
}
}
Now what exactly I am looking for is in if( ($item['single']['catid'] != 8) AND ($item['single']['catid'] != 4) ) I want allow user to add multiple category ID and each ID will add AND and further id code AND ($item['single']['catid'] != 4)
I never done this before and don't know either this is proper way to do or any other possible better way.
Thanks a lot
You should have some kind of an array of the category IDs you want to check for, for example:
$categories = array(8, 4);
Then you could use something like the in_array(needle, haystack) built-in function of PHP.
Your if condition would become like that one: if (!in_array($item['single']['catid'], $categories)) {.
You should be using the above, but I am going to give you an idea of how it works, so you can understand the principle for more complex issues:
function exists($target, $array) {
foreach ($array as $element) { // Go through each element in the array
if ($element == $target) { // Check to see if any element there is what you are searching for
return true; // Return true, that it does exist, and stop there.
} else {
// Just ignore it...
}
}
return false; // If you get here, it means nothing returned true, so it does not exist...
}
To be used as if (exists($item['single']['catid'], $categories)) {.
It wouldn't work if it was "inside" the if statement because you have to do some processing before evaluating if it exists or not. So you either could have done that before the if statement, and store the result in a variable, or use a function (which PHP provides).
Hopefully the concept will help you fir more complex problems...
Note: this assumes your input is in the form of an array, which you can build via various ways, if not provided as is directly.
Update:
The input you get via the input field is sent through form, to which you specify either POST or GET as a method. Assuming it is POST that you are using, this is how you'd get the input as a string as it was entered in the text field:
$categories_string = $_POST['the_name_field_in_the_input_tag'];
After that you have to understand it as a list of items, let's say separated by commas: 1,3,5,8. Then this is simply separating by commas. You can use explode($delimiter, $string). Like that:
$categories_array = explode(',', $_POST['categories']);
But you cannot trust the input, so you could get something like 1, 2, 3,5,6. The spaces will mess it up, because you will have spaces all around. To remove them you can use trim for example.
$categories = array(); // Create the array in which the processed input will go
foreach ($categories_array as $c) { // Go through the unprocessed one
$categories[] = trim($c) * 1; // Process it, and fill the result. The times one is just so that you get numbers in the end and not strings...
}
Then you can use it as shown earlier, but keep in mind that this is just an example, and you might not even need all these steps, and there are much more efficient ways to process this input (regular expressions for example). But the concern here is not sanitizing input, but keep in mind you will need to do that eventually.
Hope it's clear enough :)
You might be better off with in_array() for checking a value against a variable number of possibilities.
I'm not sure I understand your problem. You want user to be able to input different values, e.g.:
$string = "5, 6, 7, 8, 10";
Afterwards, you want to check if 'catid' is not in that array and if it isn't you want to run $this->list_post($item);
If so, then you should use something like this:
$values = explode(", ", $string); //make array from values
foreach ($list['post'] as $item) {
if (!in_array($item['single']['catid'], $values)) { //check whether catid is in array
$this->list_post($item); // execute whatever you want
}
}
Hope it helps.

PHP how to reuse a function from a clean state

`I have a function called lets say calculate; what i want to do is run some loops with in the function calculating an outcome. at times this function does fail as it will get stuck in a loop, so iv got it covered to exit the loop but my problem is i want to restart this function and hope it come out with an outcome if not i will try again... on average the request does not have an outcome around 1 in 20, i need to restart the function from a clean slate.
i have tried to unset all the vars before i rerun the process with out success.please note this function will fail at times from the information handed to the process, un avoidable so
when this accurs i just want to rerun the function automatically to generate an outcome.
http://www.gamezslave.com/test/DynamicSlots.swf this is my test prototype give you an idea
sometimes you refresh it will error because of this factor.
<?php
$checker = 0; // if i cant get a result i could use this will tick up until condition
function shuffleArray($myArray) {
$value_count = array_count_values($myArray);
$last_value = $myArray[count($myArray) - 1];
unset($myArray[count($myArray) - 1]);
$shuffle = array();
$last = false;
while (count($myArray) > 0) {
$keys = array_keys($myArray);
$i = round(rand(0, count($keys) - 1));
while ($last === $myArray[$keys[$i]] ) {
$i = round(rand(0, count($keys) - 1));
echo "stuck";
$checker++;
if($checker>10){
echo " Too many checks so die, and restart process ";
return false;
bob; // this is the check function to goto and restart
}
}
$shuffle[] = $myArray[$keys[$i]];
$last = $myArray[$keys[$i]];
unset($myArray[$keys[$i]]);
}
if ($last_value === $last) {
$i = 0;
foreach($shuffle as $key=>$value) {
if ($value !== $last_value) {
$i = $key;
break;
}
}
array_slice($shuffle, $i + 1, 0, $last_value);
} else {
$shuffle[] = $last_value;
}
return $shuffle;
}
print_r(shuffleArray(array(1,5,5,3,7,7,7,7))); // just a example
function bob(){
if($checker>10){
$checker = 0;
shuffleArray();
echo "bob";
reset($myArray); // thought this may clean/reset the array i couldnt use
}
}
The idea this shuffle returns that no two symbols elemts of the same will be next to each other but sometimes at the end of the array as its shuffling randomly im left with bad odds (apple, orange, orange, orange) so what i need to do is resart this process again from start take in mind there is about 10 different item in the array and duplicates of each for example 10 apples ,10 oranges 4 bannanas 3 grapes sometimes the shuffle manages to generate an outcome where im stuck with too many of the same item at the end of the array wich then i need to rerun the script(and this bit is the problem) i dont know how.
Are you using globals?
If yes: Stop that. It's terrible practice. Seriously. There's never a reason to use globals with any sort of sane code.
If no: There's nothing to do. Each function invocation is a clean slate.
EDIT After seeing the code, I'm kinda speechless.
http://us3.php.net/manual/en/function.shuffle.php
I would set defaults to all variables inside of your function, and pass anything active as a parameter. Then use a set of return codes to indicate success or failure, or validate the outcome in some way and re-run.
I'm agreeing with Tyler Eaves here and i wanted to add as another reply a very important topic in programming:
A function "should" in theory be as scalar as possible meaning that it should not affect the outside world and should return the same information everytime for the same parameters.
If you call a function with parameter X, Y and Z and call it again while your system is in the same state, the function should return the exact same result.
But if a function is not scalar (Virtual for instance), such as dependant on external data (files, database rows or single instance accessible class data) then you should theorically not affect that external data from this function or else calling the function multiple times yield different results...

Categories