Function for loops with a different process within the loop - javascript

I've got a very similar process that occurs in many places, with one small change. I was wondering what would be the best way to make the code neater. Currently, the process is:
var drawx = 0;
var drawy = 0;
while(drawy < 22){
while(drawx < 10){
if(nextBlock[drawx][drawy] != false){
base[drawx][drawy] = nextBlock[drawx][drawy];
}
drawx++;
}
drawx = 0;
drawy++;
}
Within the while drawx < 10 is where I usually have different things to run, and I'm not sure how I would create a function with a variable process in the middle of it. Is there a way to do this, or should I just create a function that does this process and executes a certain if statement depending on the parameter that was called when running the function?
EDIT: I think I might have not gotten my initial problem across. I want to be able to have a process such as the if statement within the loop to be a variable process while the rest of it to be the same

javascript has first class functions so you can do something like this:
function drawLoop(action) {
var drawx = 0;
var drawy = 0;
while(drawy < 22){
while(drawx < 10){
action(drawx, drawy);
drawx++;
}
drawx = 0;
drawy++;
}
}
And then call it like this:
drawLoop(function(drawx, drawy){
if(nextBlock[drawx][drawy] != false){
base[drawx][drawy] = nextBlock[drawx][drawy];
}
});
And of course, you can change the function you pass to drawLoop to suite your needs.

you could inject a function as a variable to your generic function like
function genericDraw(xValidation) {
var drawx = 0;
var drawy = 0;
while(drawy < 22){
while(xValidation(drawX)){
if(nextBlock[drawx][drawy] != false){
base[drawx][drawy] = nextBlock[drawx][drawy];
}
drawx++;
}
drawx = 0;
drawy++;
}
}
where xValidation is
function someValidation(value) {
return (value < 10);
}
and you call it
genericDraw(someValidation);

for( var drawy = 0 ; drawy < 22 ; drawy++) {
for( var drawx = 0 ; drawx < 10 ; drawx ++) {
if(nextBlock[drawx][drawy] != false) {
base[drawx][drawy] = nextBlock[drawx][drawy];
}
}
}

Related

Global variable not updating outside function

Trying to make variable created inside function possible to access globally, so far
console.log(proper_head);
constantly displays "1" while I need it to be updated every time the function is executed, here is my function:
var i = 0;
function change_head() {
if (i < head_class.length) {
head.classList.add(head_class[i].name);
i++;
var h = i;
return h;
} else if (i = 3) {
head.className = "";
i -= 3;
var h = i;
return h;
}
}
var proper_head = change_head();
it is executed by pressing a button (not sure if it's important).
The only solution I came up with is to
setTimeout()
I'm sure there is a better way.
You could use a recursive implementation like this:
var i = 0;
function change_head() {
if (i < head_class.length) {
head.classList.add(head_class[i].name);
i++;
var h = i;
return h;
} else if (i = 3) {
head.className = "";
i -= 3;
var h = i;
return h;
}
change_head();
}
The problem is that your function is only being called once, you can call the function from within itself, however the above example will never stop, and will probably hit the max call stack size in your browser and then crash, i would recommend wrapping it in some sort of if statement so that it stops at some point, e.g i > 50.
Edit:
I see what your actual problem is, neither of your if blocks are firing, after the first press, head_class.length === 1 so "if (i < head_class.length)" wont fire, it's also not equal to 3 for the else block so nothing happens, the else block also has an error, try changing it to this:
if (i < 3) {
head.classList.add(head_class[i].name);
i++;
var h = i;
return h;
} else if (i == 3) {
head.className = "";
i -= 3;
var h = i;
return h;
}
i = 3 is for assignment, i == 3 is for comparison.
Hope this helps
Lloyd

p5.js 27646: Uncaught TypeError: Cannot read property '0' of undefined

I was coding in JavaScript, p5.js and came across this error line:
27646: Uncaught TypeError: Cannot read property '0' of undefined
and I don't know what this means since I am not very experienced with JavaScript. It is also suspicious to me because my project does not have line 27646 anywhere.
here is my code:
var particles = [];
const word0 = 'p5.js',
word1 = 'is nice';
var active, inactive;
var cooldown;
var font;
function preload() {
font = loadFont('data/LucidaSansRegular.ttf');
}
function setup() {
createCanvas(600, 300);
active = font.textToPoints(word0, 50, 200, 200);
inactive = font.textToPoints(word1, 50, 200, 200);
cooldown = 500;
for (var i = 0; i < active.length; i++) {
particles.push(new Particle(active[i].x, active[i].y));
}
}
function draw() {
background(60);
noStroke();
fill(255);
for (var i = 0; i < particles.length; i++) {
if (particle[i].radius < 0) {
particles.splice(i, 1);
continue;
}
if (cooldown < 0) {
particles[i].forceToDes();
} else {
particles[i].fleeFromDes();
}
particles[i].update();
particles[i].show();
}
if (cooldown < 500 && cooldown > -500) {
cooldown--;
} else {
cooldown++;
}
if (cooldown == -499) {
changeText();
}
}
function changeText() {
switchActive();
if (active.length == inactive.length) {
for (var i0 = 0; i0 < active.length; i0++) {
particles[i0].des = createVector(active[i0].x, active[i0].y)
}
} else if (active.length > inactive.length) {
for (var i1 = 0; i1 < particles.length; i1++) {
particles[i1].des = createVector(active[i1].x, active[i1].y);
}
for (var i2 = 0; i2 < active.length - inactive.length; i2++) {
var p = new Particle(active[i2].x, active[i2].y),
r = particles.random();
p.pos = r.pos;
particles.push(p);
}
} else {
for (var i3 = 0; i3 < inactive.length - active.length; i3++) {
var r = floor(random(particles.length));
particles[r].shrink();
}
for (var i4 = 0; i4 < particles.length; i4++) {
particles[i4].des = createVector(active[i4].x, active[i4].y);
}
}
}
function switchActive() {
var temp = active;
active = inactive;
inactive = temp;
}
I hope you can help me :)
Thank you already!
Please post your code as an MCVE that we can copy and paste to run. When I try to run your code, I get an error because I don't have the font you're trying to load. Either include the font file or modify your code so we don't need the font file.
But just looking at your code, this sticks out to me:
for (var i = 0; i < particles.length; i++) {
if (particle[i].radius < 0) {
Here you're looping over the particles array, but then using a variable called particle. This is probably a simple typo.
I'm also suspicious of this line:
r = particles.random();
Here you're setting a variable that you haven't defined yet.
When your code contains multiple errors like this, it usually means that you aren't testing in small chunks. You should really get into the habit of working in isolation, only testing one small part until you get that working perfectly. That also makes it easier to post an MCVE if you do get stuck.
Your problem is that your word1 string has a space in it.
textToPoints() doesn't handle non-printable characters.
Try a string with no space or split your string up into to strings and combine the points arrays afterwards.
On Line 1 You define:
var particles = [];
But then you do:
if (particle[i].radius < 0) {
You defined the array "particles", not "particle", so JavaScript can't read the first value as the array "particle" doesn't exist.
Solution:
change:
if (particle[i].radius < 0) {
to:
if (particles[i].radius < 0) {

this function cause browser crash

I have written a function that i want to detect the language of the text based on utf-8 encoding.Actualy this function determines the input argumant is english or not.The function work correctly in javascript console but when I use it in a loop ,the browser crashes.
//titles.lenght=>90
function is_eng(title) {
var A = 65;
var z = 122;
title = title.toString();
var eng_chars = 0;
var non_eng_chars = 0;
for (i = 0; i < title.length; i++) {
var c = title.charCodeAt(i);
if (c > A && c < z) {
eng_chars += 1;
} else {
non_eng_chars += 1;
}
}
if (eng_chars > non_eng_chars) {
return 1;
}
return 0;
}
You should add the keyword var before i=0, otherwise i is a global variable. If you use i for the external loop, you have an endless loop.

Short way to write a long series of if-else-if's?

How to do two variables in an if condition? Here I have few else ifs and I want a 100 else ifs! Is there a shorter way?
$(document).on('click', '.btn-next', function () {
var z = [];
var recipientsArray = z.sort();
var zDuplicate = [];
$('option:selected.exclude_global').each(function() {
z.push($(this).val())});
for (var i = 0; i < recipientsArray.length - 1; i++) {
if (recipientsArray[i + 1] == recipientsArray[i]) {
zDuplicate.push(recipientsArray[i]);
}else if(recipientsArray[i + 2] == recipientsArray[i]){
zDuplicate.push(recipientsArray[i]);
}else if(recipientsArray[i + 3] == recipientsArray[i]){
zDuplicate.push(recipientsArray[i]);
}else if(recipientsArray[i + 4] == recipientsArray[i]){
zDuplicate.push(recipientsArray[i]);
}
}
if(zDuplicate.length>>0){
alert("Global Filter Already Exists");
event.preventDefault();
}
});
Here I have few else ifs and I want a 100 else ifs! Is there a shorter way? I have a dynamic table with dynamic rows. when my table has 5 rows the code is working, but when I have more its not working.
What you're looking for is called a nested loop. You basically can write a loop within a loop. (As many as you want, actually. Though it can get ugly fast.)
Consider your loop structure:
for (var i = 0; i < recipientsArray.length - 1; i++) {
// check if recipientsArray[i] equals any other element
}
Well, that's just another loop:
for (var i = 0; i < recipientsArray.length - 1; i++) {
for (var j = i + 1; j < recipientsArray.length - 1; j++) {
if (recipientsArray[j] == recipientsArray[i]) {
zDuplicate.push(recipientsArray[i]);
break;
}
}
}
Note that there's probably a more efficient way of checking for duplicates. (Especially if the collection is sorted.) At the very least I've changed the logic so you're not re-comparing comparisons you've already made. (I did this by starting the inner loop at i + 1 instead of 1 as your logic does.)
I also think I've replicated your else if results by using a break statement. Since your else if logic basically means "once you find one, stop looking". That's what this break should do, or at least is intended to do, but you'll want to test that. If it doesn't (nesting can be confusing sometimes, which is why it should be done carefully) then you can probably make use of labels to achieve the same effect.
Ultimately, however you implement it, the concept is the same. You're asking how to iterate over multiple values in an array. That's what a loop is for.
I don't know that language. But data and control structures are data and control structures in any language.
Substitute your for loop by :
for (var i = 0; i < recipientsArray.length - 1; i++) {
for ( var j = i+1; j < recipientsArray.lenght-1; j++) {
if (recipientsArray[i] == recipientsArray[j]) {
zDuplicate.push(recipientsArray[i]);
break;
}
}
}
Thank you so much for the idea!
A small change to your code works like heaven!
for (var i = 0; i < recipientsArray.length - 1; i++) {
for (var j = 1; j < 100; j++) {
if (recipientsArray[i+j] == recipientsArray[i]) {
zDuplicate.push(recipientsArray[i]);
break;
}
}
}

How to cycle between two arrays

I'm trying to create a cycling sliding animation for set of elements, i have two arrays:
var elms = [elm1, elm2, elm3];
var props = [{x,y,width,height,z-index,opacite,....}, {....}, {....}];
on initializing, elms will be positioned in the same order as props: "-> is not part of the syntax it's just to make things easier to explain and it means 'do something with'"
elms[0] -> props[0];
emls[1] -> props[1];
elms[2] -> props[2];
but then i want to cycle them like:
elms[0] -> props[2]
elms[1] -> props[0]
elms[2] -> props[1]
and then:
elms[0] -> props[1]
elms[1] -> props[2]
elms[2] -> props[0]
and so forth...
i tried this:
function index(n, array){
var m = n;
if(n > array.length){
m = n - array.lenth;
}else if(n < 0){
m = array.length + n;
}
return m;
}
var active = 0; //the front element
function slide(direction){
for (i=0; i< elms.length; i++)
{
elms[i] -> props[index(i - active, props)]
}
if(direction == 'fw'){
if(active++ => elms.length){
active = 0;
}else{
active++;
}
}else if(direction == 'bw'){
if(active-- < 0){
active += elms.length;
}else{
active--;
}
}
}
setInterval(function(){slide('fw')}, 3000);
now the above code works fine, but i'm sure this has been done many times before and i'm wondering does anyone know if there is a better less complicated way to do this which allows to loop forward and backward?
If you don't mind modifying the props array, you can just .shift() off the first element and then .push() is onto the end of the array and then once again do:
elms[0] -> props[0];
emls[1] -> props[1];
elms[2] -> props[2];
To rotate the props array, you could just do this:
function rotateProps() {
var front = props.shift();
props.push(front);
}
So, each cycle just call rotateProps() and then repeat what you did the first time.
How about using module? Have a global var that you increment each time you shift, then module that with the length of the arrays. You could access the arrays like: props[shift%len]
If len is 3 (as above), you could get these results if you are accessing the props in relation to the first elmsIdx (0):
POC: jsfiddle.net/Q8dBb, also this would work without modifying your arrays so I believe it would be faster
shift = 0; // (shift+elmsIdx)%len == 0;
shift = 1; // (shift+elmsIdx)%len == 1;
shift = 2; // (shift+elmsIdx)%len == 2;
shift = 3; // (shift+elmsIdx)%len == 0;
shift = 4; // (shift+elmsIdx)%len == 1;
etc
Actually, using an object could make it more flexible (shifting multiple ways, resetting, whatever you want to add). Here is an example for that:
function Shift(len) {
var _len = len;
var _s = 0;
this.left = function() {
_s = (_s + 1)% _len;
}
this.right = function() {
_s = (_s - 1);
if (_s < 0) {
_s = _s + _len;
}
}
this.get = function(idx) {
return (_s + idx)% _len;
}
this.reset = function() {
_s = 0;
}
}
in use: http://jsfiddle.net/6tSup/1/

Categories

Resources