Javascript: an array in While loop isn't changing when it should - javascript

I have a while loop that's working fine. Inside it is an array push. yes this part works perfectly until the while loops completes. All of this is inside another while loop what has an increment change. the increment affects the array in hopes to re-write it completely. what ends up happening is that it stays stuck on the first version of the array, and everything else in later coding can't call on the second version of the array.
var arrayname = [];
var increment = 0;
var var1 = 0;
var x = 0;
var y = 0;
var z = 0;
outerloop == 0;
while(outerloop == 0){
endloop = 0;
while (endloop == 0) {
arrayname.length = 0;
randomFunctionThatCreatesThe123variables();//in here 'increment' changes output.
x = (1 + 2 + 3); //above function's summed result
y = 25; //static base number
alert(increment);
z = (increment + y);
if (x == z)
arrayname[array.length] = [1,2,3];
if (x == 500)
endloop = 1;
}
testloop = 0;
while (testloop == 0){
otherRandomFunctionsThatTestArray();//this loops the same functions on each subarray
if (var1 == arrayname.length) {
testloop = 1;
var1 = 0;
tar = ++increment;
}
}
if((increment + y) == 700)
outerloop = 1;
}
my goal is that the testloop functions test the array, then when endloop recreates the array on the next cycle, it will use the newly incremented affected array. but all that happens is:
if array not cleared:it keeps cycling the tests throught the same array.
if cleared with arrayname.length = 0; the tests use the new increment to find the new array and but finds it undefined.
the alert proves the increment is being properly read.

Related

Cannot iterate while statement

NEWB question. Be patient.
As an exercise I am trying to create a grid simply by appending to innerHTML.
I cannot get the loop to repeat beyond its first iteration. I'm sure it's something basic but I have to start somewhere.
I've tried "let" instead of "var", console.log instead of document..., hours of googling.....
var originalSize = 8;
var sizeGrid = 0;
var heightGrid = 0;
var switchChar = 2;
var switchCharTwo = 1;
var charOne = "x";
var charTwo = "#";
while (heightGrid <= originalSize){
document.getElementById("el").innerHTML+="<br>";
if (switchChar % 2 === 0){
switchCharTwo = 1;
}
else {
switchCharTwo = 2;
}
while (sizeGrid <= originalSize){
if (switchCharTwo % 2 === 0){
document.getElementById("el").innerHTML+=charOne;
}
else {
document.getElementById("el").innerHTML+=charTwo;
}
sizeGrid = sizeGrid + 1;
switchCharTwo = switchCharTwo + 1;
}
heightGrid = heightGrid + 1;
switchChar = switchChar + 1;
}
<html>
<body>
<p id="el"></p>
</body>
</html>
What I want is:
#*#*#*#*#
*#*#*#*#*
#*#*#*#*#
etc. depending on the size of the grid.
All I get is one line of the above.
The problem is in the sizeGrid which is stopping the inner loop by doing this it will work fine.
while (heightGrid <= originalSize){
sizeGrid = 0;
document.getElementById("el").innerHTML+="<br>";
if (switchChar % 2 === 0){
switchCharTwo = 1;
}
else {
switchCharTwo = 2;
}
while (sizeGrid <= originalSize){
if (switchCharTwo % 2 === 0){
document.getElementById("el").innerHTML+=charOne;
}
else {
document.getElementById("el").innerHTML+=charTwo;
}
sizeGrid = sizeGrid + 1;
switchCharTwo = switchCharTwo + 1;
}
heightGrid = heightGrid + 1;
switchChar = switchChar + 1;
}
Your code contains two loops with one nested inside of the other.
Your nested loop is going to run on the first iteration while it meets the given condition, sizeGrid <= originalSize. On all subsequent iterations of the main loop however, the given condition has already been met. The value wasn't reset between loops therefore the nested loop doesn't run again.
This could be resolved with a quick update by moving the sizeGrid variable declaration within the main loop:
while (heightGrid <= originalSize) {
var sizeGrid = 0;
Given what you're looking to achieve however, you could condense this down with a different loop type.
You've essentially manually written a for loop. You set the starting counter value, run the loop, and then increment your counter. Here's the approach I'd suggest:
for (let heightGrid = 0; heightGrid <= originalSize; heightGrid++) {
... logic here
// nested loop
for (let sizeGrid = 0; sizeGrid <= originalSize; sizeGrid++) {
// nested logic
}
}
You'll have to be careful with the comparisons however. Your original loop iterates 10 times despite originalSize being 8. The for loop above will actually run 9 times which seems to match the output you're looking for. I'd be inclined to adjust your numbering so that it's clearer though.
Here's a rough approach I came up with:
const gridSize = 9;
const gridChars = ['x', '#'];
let gridCharCounter = 0;
for (let rows = 0; rows < gridSize; rows++) {
for (let columns = 0; columns < gridSize; columns++) {
const charKey = gridCharCounter % gridChars.length;
document.getElementById("el").innerHTML += gridChars[ charKey ];
gridCharCounter++;
}
document.getElementById("el").innerHTML += '<br />';
}

All three if statements in a for loop triggering when only one is true (JavaScript)

This has me a little stumped. Whenever I execute this code, if one of the if statements in the for loop are true, all three sub-arrays of weaknessArray get effected. The same thing happens when each if statement is in it's own for loop and if instead of one 2D array I use a three separate arrays, one for each for loop.
var typeChart = [2,2,2,2,2,2,4,2,2,2,2,2,2,0,2,2,2,2];
var blankArray = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var weaknessArray = [blankArray,blankArray,blankArray];
for(i = 0; i<18; i++){
if(typeChart[i] === 0) weaknessArray[2][i] = 1;
if(typeChart[i] === 1) weaknessArray[1][i] = 1;
if(typeChart[i] === 4) weaknessArray[0][i] = 1;
console.log(weaknessArray);
}
There is only ever one blankArray object in memory; your weaknessArray contains three references to the same object.
Create copies instead with .slice, so that you have three arrays (well, four, counting the original) in memory instead of one:
var typeChart = [2,2,2,2,2,2,4,2,2,2,2,2,2,0,2,2,2,2];
var blankArray = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var weaknessArray = [blankArray.slice(), blankArray.slice(), blankArray.slice()];
for(i = 0; i<18; i++){
if(typeChart[i] === 0) weaknessArray[2][i] = 1;
if(typeChart[i] === 1) weaknessArray[1][i] = 1;
if(typeChart[i] === 4) weaknessArray[0][i] = 1;
console.log(weaknessArray);
}

Javascript changing value in multidimensional array

I try to to fill a multidimensional Array with the content from an Json file.
The problem is, I can´t update the content in the Array:
if(j>i && hoursYy == hoursY && secondsX == secondsXx){
wocheArray[i].count = wocheArray[i].count + 1;
}
My goal was, that "count" counts up, every time I find a duplicate in my JSON file. I couldn't´t find an answer online jet.
just in case, here is the whole code:
var myweek;
var x;
var y;
var id;
var count;
var wocheArray = [];
function preload(){
myweek = loadJSON("data/data.json");
}
function setup(){
createCanvas(windowWidth, windowHeight);
background(0);
//SAVE IN WOCHEARRAY
for (var i = 0; i < myweek.woche.length; i++) {
hoursY = myweek.woche[i].stunden;
secondsX = myweek.woche[i].sekunden;
for (var j=0; j< myweek.woche.length; j++){
hoursYy = myweek.woche[j].stunden;
secondsXx = myweek.woche[j].sekunden;
if(j>i && hoursYy == hoursY && secondsX == secondsXx){
wocheArray[i].count = wocheArray[i].count + 1;
}
else {
x = myweek.woche[i].stunden;
y = myweek.woche[i].sekunden;
id = myweek.woche[i].person;
count = 0;
}
wocheArray[i] = {x, y, count, id};
}
}
console.log(wocheArray);
}
The problem reside here :
wocheArray[i] = {x, y, count, id};
If you check your code you would find that this part is overriding.
Consider your case: If a duplicate is found.
Then what your for loop will do:-
1.) Set var count = 0;
2.) [Skipping to If condition where is the procedure to check]
//IF match found (at j = 2 location, and i = 1)
//then what happen is :
if(2>1 && hoursYy == hoursY && secondsX == secondsXx){
wocheArray[1].count = wocheArray[1].count + 1;
// from here the count of wocheArray[1] would be increased by 1, Suppose 1.
}
3) In else block it will again set count = 0;
4) Again you are trying to set the values of wocheArray[1] = {x, y, count, id}; //now wocheArray[1] count is set to 0.
So from here, you can see you are updating the values or overriding them which creating the undesired result.
You should not call this outside wocheArray[i] = {x, y, count, id};
You must call it inside else block to make it work correctly.
else{
x = ....
....
....
count = 0;
wocheArray[i] = {x, y, count, id};
}
However, I am curious about the using of count = 0; inside else block as it does nothing here and var count =0; inside the for block which just re-initializes count variable which is wasting memory or not a good practice. According to shown code sample.
If you format your code a bit better, you will see that
wocheArray[i] = {x, y, count, id};
is outside your if else. So wocheArray[i] is overwritten at the end of every loop.

multidimensional array indexOf not working js

I'm trying to find an index of a number in a 2d array, but console gives out
Uncaught TypeError: block[((a * 10) + c)].indexOf is not a function
I think it has something to do with the way of accessing the array element, but can't seem to find the problem.
Here's the code.
var block = [];
var temp;
var del;
for(var a = 0;a < 9;a++){
for(var b = 0;b < 9;b++){
temp = parseInt(prompt("enter element number " + b + " of row number " + a));
console.log(temp);
if(temp>0){
block[a*10+b] = temp;
}else{
block[a*10+b] = [1,2,3,4,5,6,7,8,9];
}
// console.log(block[a*10+b]);
}
}
for(var a = 0;a < 9;a++){
for(var b = 0;b < 9;b++){
if(typeof(block[a][b]) == "number"){
for(var c = 0;c < 9;c++){
if(c != b){
del = block[a*10+c].indexOf(b);
block[a*10+c].splice(del,1);
}
}
}
}
}
You have a mix of data types assigned to the block array. When the user enters a value that is not numeric, you assign indeed a nested array to one of the block elements, but not so when the user enters a valid number.
From what I think you are doing (a Sudoko game?) this might be intended: the numbers are known values in the grid, the nested arrays represent a list of values that are still possible at that particular cell.
But then in the second part of your code, you should check in which of the two cases you are, as you only want to remove array elements if the value you are looking at is indeed an array. This test you can do with Array.isArray().
There are also some other issues in the second part of your script:
The expression block[a][b] is not consistent with how you have filled that array: it should be block[a*10+b] to be consistent.
the b in .indexOf(b) is wrong: you are not looking for that value, but for block[a*10+b].
the splice() is always executed, even if the indexOf returned -1. This leads to an undesired effect, because if the first argument to splice() is negative, the index really is counted from the end of the array, and still an element is removed from the array. This should not happen: you should only execute the splice if the indexOf result is non-negative.
Below I have put a working version, but in order to avoid the almost endless prompts, I have provided this snippet with a textarea where you can input the complete 9x9 grid in one go, and then press a button to start the execution of your code:
document.querySelector('button').onclick = function () {
var block = [];
var temp;
var del;
var text = document.querySelector('textarea').value.replace(/\s+/g, '');
for(var a = 0;a < 9;a++){
for(var b = 0;b < 9;b++){
temp = parseInt(text[a*9+b]); // <-- get char from text area
if(temp>0){
block[a*10+b] = temp;
}else{
block[a*10+b] = [1,2,3,4,5,6,7,8,9];
}
}
}
for(var a = 0;a < 9;a++){
for(var b = 0;b < 9;b++){
var num = block[a*10+b]; // <-- get content, fix the index issue
if(typeof num == "number"){
for(var c = 0;c < 9;c++){
if(c != b && Array.isArray(block[a*10+c])){ //<-- add array-test
del = block[a*10+c].indexOf(num); // <-- not b, but num
if (del > -1) // <-- only splice when found
block[a*10+c].splice(del,1);
}
}
}
}
}
document.querySelector('pre').textContent = 'block='+ JSON.stringify(block);
};
<textarea rows=9>
53..7....
6..195...
.98....6.
8...6...3
4..8.3..1
7...2...6
.6....28.
...419..5
....8..79
</textarea>
<button>Process</button>
<pre></pre>
Note that there are elements in block which remain null. I suppose you intended this: as you multiply a with 10, and only store 9 values per "row", there is always one index that remains untouched.
I haven't looked over your second for loop, but you can try applying similar logic there as in the snippet I've provided. The issue is that you need to create a temporary array inside the outer for loop over values of a (but NOT inside the inner, nested for loop over values of b). Inside the for loop for values of b, then, you need to push something into that temporary array (which I called temp). Then, outside of the b for loop, but before the next iteration of a, push that temporary array temp to the block array. In this way, you will generate a 2D array.
var block = [];
var del;
for(var a = 0; a < 9; a++) {
let temp = [];
for(var b = 0; b < 9; b++) {
let num = parseInt(prompt(`Enter element ${b} of row ${a}:`));
if (num > 0) {
temp.push(num);
} else {
// block[a*10+b] = [1,2,3,4,5,6,7,8,9];
temp.push(b);
}
}
block.push(temp);
}

js Bubble sort not processing all elements correctly

I pass in elements array [5,4,3]. The bubble sort manages to push 5 the end, this is fine, but when it loops through a third time to locate the second to last element, the loop breaks and the incorrect ordered array is returned... not sure why, cheers guys
this.bubbleSort = function (elements) {
//Loop through to the second to last index. By the time we get to the last index, its already //been compared with what’s in front of it
var hasHadChange;
for (var x = 0; x < elements.length - 1; x++) {
hasHadChange = false;
//Loop through to the second to last index.
for (var y = 0; y < elements.length - 1; y++) {
//Check the current item(x) in the array plus the item next to current item (x+1), if its larger
if (elements[y] > elements[y + 1]) {
//Acknowledge there has been a change
hasHadChange = true;
//Swap the items around
var temp = elements[y];
elements[y] = elements[y + 1];
elements[y + 1] = temp;
//This continues until the largest value has bubbled to the right
}
}
}
return elements;
}
You need to use separate variables for the inner and the outer loop. When you exit the inner loop, x will be equal to the length, so the outer loop will end also.
You should use separate variables in inner and outer loops. Using y in inner loop instead will give you the correct answer.
var bubbleSort = function (elements) {
//Loop through to the second to last index. By the time we get to the last index, its already //been compared with what’s in front of it
var hasHadChange;
for (var x = 0; x < elements.length - 1; x++) {
hasHadChange = false;
//Loop through to the second to last index.
for (y = 0; y < elements.length - 1; y++) {
//Check the current item(x) in the array plus the item next to current item (x+1), if its larger
if (elements[y] > elements[y + 1]) {
//Acknowledge there has been a change
hasHadChange = true;
//Swap the items around
var temp = elements[y];
elements[y] = elements[y + 1];
elements[y + 1] = temp;
//This continues until the largest value has bubbled to the right
}
}
}
return elements;
}
The reason behind this is variable hoisting.
When a variable is declared, it breaks into two parts. One part moves to top of it's scope, other stays at it's position. For Example,
function foo() {
if (false) {
var x = 1;
}
var y = 1;
}
Will look like :
function foo() {
var x = undefined; //Declaration of x is hoisted
var y = undefined; //Declaration of y is hoisted
if (false) {
x = 1; //Assignment still occurs where we intended
}
y = 1; //Assignment still occurs where we intended
}
This is what happened in the code. Using same variable in both loops makes them overwrite each other values. Hence the result.
From ECMAScript standard 5.1 :
A variable statement declares variables that are created as defined in 10.5. Variables are initialised to undefined when created. A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement is executed, not when the variable is created.
See this MDN doc for more details. Look for topic var hoisting.
Update
Using let which has block level scope, you can have variable x in both loops.
var bubbleSort = function (elements) {
//Loop through to the second to last index. By the time we get to the last index, its already //been compared with what’s in front of it
var hasHadChange;
for (var x = 0; x < elements.length - 1; x++) {
hasHadChange = false;
//Loop through to the second to last index.
for (let x = 0; x < elements.length - 1; x++) {
//Check the current item(x) in the array plus the item next to current item (x+1), if its larger
if (elements[x] > elements[x + 1]) {
//Acknowledge there has been a change
hasHadChange = true;
//Swap the items around
var temp = elements[x];
elements[x] = elements[x + 1];
elements[x + 1] = temp;
//This continues until the largest value has bubbled to the right
}
}
}
return elements;
}
You are using the same control variable x for both for-cycles, should use different like x and y for example.

Categories

Resources