Javascript changing value in multidimensional array - javascript

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.

Related

Algorithm to calculate if 'n' or more intervals intersect & the total of the respective intersections

I need help developing a weird algorithm. I have a JavaScript object containing people and an array for each person of start and end time intervals in milliseconds:
var person = [
(1533242595, 1533242999),
(1533242595, 1533242999),
(1533242595, 1533242999)
]
I need to determine if any intervals intersect/overlap, but for n or more intersections (for example, determining if 4+ intervals overlap) and calculate the total sum of the n or more intersecting intervals.
A function that takes a n parameter and the person object would be perfect.
First the person must be defined as list of lists:
var person = [
[1533242595, 1533242999],
[1533242595, 1533242999],
[1533242595, 1533242999]
];
Here you can find a sample of function:
function limit_intersection(limit, person) {
var arrayLength = person.length;
var intersections = 0;
var intersectionsum = 0;
var min, max = 0;
var tmp;
var intervals = [];
for (var i = 0; i < arrayLength-1; i++) {
if(person[i][0] > person[i][1]) {
tmp = person[i][1];
person[i][1] = person[i][0];
person[i][0] = tmp;
}
for (var j = i+1; j < arrayLength; j++) {
if(person[j][0] > person[j][1]) {
tmp = person[j][1];
person[j][1] = person[j][0];
person[j][0] = tmp;
}
min = 0;
max = 0;
if(person[i][1] <= person[j][0] || person[i][0] >= person[j][1]){
// no intersection
continue;
}
intersections +=1;
if(person[i][0] >= person[j][0]) {
min = person[i][0];
} else {
min = person[j][0];
}
if(person[i][1] >= person[j][1]) {
max = person[j][1];
} else {
max = person[i][1];
}
intervals.push([min,max]);
intersectionsum += max-min;
}
}
return {'n' : intersections, 'sum' : intersectionsum, 'intervals' : intervals};
}
An here the working demo on jsfiddle.net
Are you sure that's how your data is structured? Because that does not look like a Javascript object to me, correct me if I'm wrong.
Break your code in to bite sized problems. What is an overlap? How do we check if two intervals overlap each other? When you make that function, use that to loop through your person intervals. Make a variable that contains the sum of the matches and return that.
function overlaps(startX, endX, startY, endY) {
if(endX < startY || endY < startX) return false;
return true;
}
console.log(overlaps(1,2,1,4)) // true
console.log(overlaps(10,20,1,11)) // true
console.log(overlaps(1,2,3,4)) // false
console.log(overlaps(4,3,2,1)) // false
Now find a way to loop over your persons checking for overlaps with this bite sized function.
Edited, here's an example of answer with bite-sized readable functions instead of the spagetti code in the selected answer:
// Check if two intervals overlap
function overlaps(startX, endX, startY, endY) {
if(endX < startY || endY < startX) return false;
return true;
}
// Check how many times two person arrays overlap
function comparePersons(person1, person2){
var matches = 0;
person1.forEach(function(elementX) {
person2.forEach(function(elementY) {
if(overlaps(
elementX[0],elementX[1],
elementY[0],elementY[1]
)) matches +=1
});
});
return matches;
}
// Check how many times all persons overlap with another
function compareAll(persons, n){
var totalMatches = 0;
persons.forEach(function(element, index1) {
var compareMatches = 0;
persons.forEach(function(compareElement, index2) {
if(index1 !== index2) {
compareMatches += comparePersons(element, compareElement)
}
});
if(compareMatches >= n) totalMatches += 1;
});
return totalMatches;
}
// Create persons to test
var person1 = [
[10,20],
[100,200]
]
var person2 = [
[1,2000],
[50,1000]
]
var person3 = [
[10,200],
[0,1],
[1000,2000],
[100,2000]
]
// Create one array with all persons
var allPersons = [
person1, person2, person3
]
// Test by console logging
console.log(compareAll(allPersons, 5));

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

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.

scriptProcessorNode.onaudioprocess not able to access global variables

I am building class around a scriptProcessorNode oscillator. I have wrapped my onaudioprocess event handler in a function Gendy.prototype.process. I can access global variables and functions from within this wrapper function, but they are not accessible from within the onaudioprocess function.
I devised a work around for the properties, to redefine them in the wrapper function, but this doesn't work when trying to call another method, a random walk method, with this.walk().
Here is my code:
Gendy.prototype.process = function(){
var point = 0;
var index = 0;
var y = 0;
var breakpoint = this.breakpoint;
var freq = this.freq;
var walk = this.walk();
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
var outputBuffer = audioProcessingEvent.outputBuffer;
var outputData = outputBuffer.getChannelData(0);
for(var j = 0; j < outputData.length;j++){
// linearly interpolate between the new breakpoint positions
// get the interp point by comparing index to the x distance
var lerp = (index - breakpoint[point].x) / (breakpoint[point+1].x - breakpoint[point].x);
y = lerp * (breakpoint[point+1].y - breakpoint[point].y) + breakpoint[point].y;
if(point < breakpoint.length && index >= breakpoint[point+1].x) {
point++;
}
outputData[j] = y;
index+=freq;
if(index >= breakpoint[breakpoint.length-1].x){
index = 0;
point = 0;
walk();
}
}
}
}
This makes sound, but returns the errors:
Uncaught TypeError: walk is not a function
for few lines and then
Uncaught TypeError: undefined is not a function
forever.
Is this a bug with the scriptProcessorNode? Any insight would be appreciated!
no bug in scriptProcessorNode, the issue is the below line:
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
the this varible inside the onaudioprocess would refer to this.scriptNode object by default, you can handle it in one of two ways:
Use bind( as you have done in your answer):
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
...
}.bind(this)
use a local variable to hold the value of this, and use that local variable in place of this:
var self = this;
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
...
I was able to access this from within the onaudioprocess function by attaching .bind(this) to it.
Here is the code:
Gendy.prototype.process = function(){
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
var outputBuffer = audioProcessingEvent.outputBuffer;
var outputData = outputBuffer.getChannelData(0);
for(var j = 0; j < outputData.length;j++){
// linearly interpolate between the new breakpoint positions
// get the interp point by comparing index to the x distance
var lerp = (this.index - this.breakpoint[this.point].x) / (this.breakpoint[this.point+1].x - this.breakpoint[this.point].x);
this.y = lerp * (this.breakpoint[this.point+1].y - this.breakpoint[this.point].y) + this.breakpoint[this.point].y;
if(this.point < this.breakpoint.length && this.index >= this.breakpoint[this.point+1].x) {
this.point++;
}
outputData[j] = this.y;
this.index+=this.freq;
if(this.index >= this.breakpoint[this.breakpoint.length-1].x){
this.index = 0;
this.point = 0;
this.walk();
}
}
}.bind(this);
}

can't convert undefined to object in javascript

Update: I have added the fiddle. Please refer here. use web console for error.
I am writing a code for traveling salesman problem. Here is the code :
var ind =[]; //values selected
var cp =[];
var X;
var Y;
var tour = [];
// no values selected in the starting
for(j=0;j<friends_cnt;j++) {
ind[j] = 0;
}
// distances at i,i infinity
for(i=0;i<friends_cnt;i++) {
distance[i][i] = 9999999999999;
}
var k = 0;
var X = 0;
tour[k] = X;
ind[X] = 1;
var i =1;
while(i<friends_cnt && ind[i] === 0) {
var min = 9999999999999;
// finding minimum of the undeleted values
for(j=0;j<friends_cnt;j++) {
if(ind[j] === 0) {
if(distance[X][j] < min) {
min = distance[X][j];
Y = j; // y is the min city
}
}
}
k = k+1; // counter for the starting city
tour[k] = Y; //city added
ind[Y] = 1;
X = Y;
i++;
}
k = k+1;
tour[k] = tour[1];
for(var q=0;q<k+1;q++) {
console.log(tour[q]);
}
});
});
now here whenever i run my program, it shows an error
TypeError: can't convert undefined to object
in the line
var min = 9999999999999;
My question is that is this because JavaScript cant handle large numbers or something else ?
Javascript's max number is 1.7976931348623157e+308 (aka the var Number.MAX_VALUE), so that shouldn't be an issue.
If you are trying to access an object of an object, it won't work.
You have distance[X][j]. That tries to access key j of distance[X]. To fix this, define distance[X] as an object:
distance[X] = [];
Other example:
var distance = [];
distance[i]
//undefined;
distance[i][i]
//syntax error
distance[i] = [];
distance[i][i]
//undefined;
For 2D arrays, see this question.
The problem is actually here:
distance[i][i] = 9999999999999;
If distance is undefined or an empty array, that statement will fail. This should fix it:
var distance = []; // <-- this is missing from the top of your code
// ...
if (!distance[i]) {
distance[i] = [];
}
distance[i][i] = 9999999999999;
Try this for minimum number
var min = int.MinValue
For max number
var max = int.MaxValue
Edited
Refer Reference
Number.Max_Value
Number.Min_Value
UPDATED
If you see your code you have filled the ind[] from 0
for(j=0;j<friends_cnt;j++) {
ind[j] = 0;
}
and in your while condition you have set value of i from 1. So for the last element it may be throwing error

Ordering z-indexes in an array

I have an array which looks something along the lines of
resourceData[0][0] = "pic1.jpg";
resourceData[0][1] = 5;
resourceData[1][0] = "pic2.jpg";
resourceData[1][1] = 2;
resourceData[2][0] = "pic3.jpg";
resourceData[2][1] = 900;
resourceData[3][0] = "pic4.jpg";
resourceData[3][1] = 1;
The numeric represents the z-index of the image. Minimum z-index value is 1. Maximum (not really important) is 2000.
I have all the rendering and setting z-indexes done fine. My question is, I want to have four functions:
// Brings image to z front
function bringToFront(resourceIndex) {
// Set z-index to max + 1
resourceData[resourceIndex][1] = getBiggestZindex() + 1;
// Change CSS property of image to bring to front
$('#imgD' + resourceIndex).css("z-index", resourceData[resourceIndex][1]);
}
function bringUpOne(resourceIndex) {
}
function bringDownOne(resourceIndex) {
}
// Send to back z
function sendToBack(resourceIndex) {
}
So given then index [3] (900 z):
If we send it to the back, it will take the value 1, and [3] will have to go to 2, but that conflicts with [1] who has a 2 z-index so they need to go to three etc.
Is there an easy programatical way of doing this because as soon as I start doing this it's going to get messy.
It's important that the indexes of the array don't change. We can't sort the array unfortunately due to design.
Update
Thanks for answers, I'll post the functions here once they are written incase anyone comes across this in the future (note this code has zindex listed in [6])
// Send to back z
function sendToBack(resourceIndex) {
resourceData[resourceIndex][6] = 1;
$('#imgD' + resourceIndex).css("z-index", 1);
for (i = 0; i < resourceData.length; i++) {
if (i != resourceIndex) {
resourceData[i][6]++;
$('#imgD' + i).css("z-index", resourceData[i][6]);
}
}
}
Loops! This function will reorder affected images around it. It will work with images that have widely separated z-index values. It also does not perform any changes unless it needs to.
EDIT: added function to do the CSS work
EDIT 2: Corrected problem with top/bottom functions - it wasn't moving all the images affected, now it is.
var resourceData = Array();
resourceData[0] = Array();
resourceData[0][0] = "pic1.jpg";
resourceData[0][1] = 5;
resourceData[1] = Array();
resourceData[1][0] = "pic2.jpg";
resourceData[1][1] = 2;
resourceData[2] = Array();
resourceData[2][0] = "pic3.jpg";
resourceData[2][1] = 900;
resourceData[3] = Array();
resourceData[3][0] = "pic4.jpg";
resourceData[3][1] = 1;
function _doMoveImage(ptr) {
// Change CSS property of image
$('#imgD' + ptr).css("z-index", resourceData[ptr][1]);
}
// Brings image to z front
function bringToFront(resourceIndex) {
var highest_idx = 0;
for (var i = 0; i < resourceData.length; i++) {
// for all images except the target
if (i != resourceIndex) {
// preserve the highest index we encounter
if (highest_idx < resourceData[i][1])
highest_idx = resourceData[i][1];
// move any images higher than the target down by one
if (resourceData[i][1] > resourceData[resourceIndex][1]) {
resourceData[i][1]--;
_doMoveImage(i);
}
}
}
// now move the target to the highest spot, only if needed
if (resourceData[resourceIndex][1] < highest_idx) {
resourceData[resourceIndex][1] = highest_idx;
_doMoveImage(resourceIndex);
}
return;
}
function bringUpOne(resourceIndex) {
var next_idx = 2000;
var next_ptr = false;
for (var i =0; i < resourceData.length; i++) {
// for all images except the target
if (
i != resourceIndex &&
next_idx > resourceData[i][1] &&
resourceData[i][1] > resourceData[resourceIndex][1]
){
next_idx = resourceData[i][1];
next_ptr = i;
}
}
// only move if needed
if (next_ptr) {
// target takes next's index
resourceData[resourceIndex][1] = resourceData[next_ptr][1];
// next's index decreases by one
resourceData[next_ptr][1]--;
_doMoveImage(resourceIndex);
_doMoveImage(next_ptr);
}
return;
}
function bringDownOne(resourceIndex) {
var next_idx = 0;
var next_ptr = false;
for (var i =0; i < resourceData.length; i++) {
// for all images except the target
if (
i != resourceIndex &&
next_idx < resourceData[i][1] &&
resourceData[i][1] < resourceData[resourceIndex][1]
){
next_idx = resourceData[i][1];
next_ptr = i;
}
}
// only move if needed
if (next_ptr) {
// target takes next's index
resourceData[resourceIndex][1] = resourceData[next_ptr][1];
// next's index decreases by one
resourceData[next_ptr][1]++;
_doMoveImage(resourceIndex);
_doMoveImage(next_ptr);
}
}
// Send to back z
function sendToBack(resourceIndex) {
var lowest_idx = 2000;
for (var i = 0; i < resourceData.length; i++) {
// for all images except the target
if (i != resourceIndex) {
// preserve the lowest index we encounter
if (lowest_idx > resourceData[i][1])
lowest_idx = resourceData[i][1];
// move any images lower than the target up by one
if (resourceData[i][1] < resourceData[resourceIndex][1]) {
resourceData[i][1]++;
_doMoveImage(i);
}
}
}
// now move the target to the lowest spot, only if needed
if (resourceData[resourceIndex][1] > lowest_idx) {
resourceData[resourceIndex][1] = lowest_idx;
_doMoveImage(resourceIndex);
}
return;
}
There it is: copy your structure and have it properly ordered, or if you prefer call it indexed. When you need the picture find the proper z-index and proceed w/ the rendering.
You can do that dynamically and use heap, if you don't wish to copy the entire structure.
Not tested, but how about this. For bringUpOne, bringDownOne one you can swap the z-indexes, e.g:
function bringUpOne(resourceIndex) {
var myZIndex = resourceData[resourceIndex][1];
var nextZIndex = resourceData[resourceIndex + 1][1];
resourceData[resourceIndex][1] = nextZIndex;
resourceData[resourceIndex + 1][1] = myZindex;
}
For bringing to the front:
function bringToFront(resourceIndex) {
var maxZIndex = resourceData[maxResourceIndex][1];
resourceData[resourceIndex][1] = maxZIndex + 1;
}
Now that's all fine. But what happens if you want to successively set images to the back? You can either set the zIndex to 0 each time (don't know how many you'll have actually visiable at any time) or you can start with the lowest zIndex set to something like 2000 or 10000 or whatever, which will acccomodate many calls to setToBack.
Edit: This assumes the list is ordered by zIndex to start with.

Categories

Resources