I have a node system, which stores a bunch of nodes that are connected to other nodes. The data is structured like this:
[
{"id":0,"x":1,"y":2, "linksTo":[1]},
{"id":1,"x":3,"y":4, "linksTo":[0,2,3]},
{"id":2,"x":5,"y":6, "linksTo":[1,4]},
{"id":3,"x":3,"y":10,"linksTo":[1,4]},
{"id":4,"x":5,"y":12,"linksTo":[2,3]}
]
What I'm trying to do is delete a certain node, and all references to that in the other nodes that might be "linked" to it based on its ID.
I've gotten to the point where I can get the node i need using this function:
function getNode(id, y){
var x;
if(y){ x = id; }
if(x && y){
var nodeAtPos = false;
Object.keys(paths.list).forEach(function(i){
if(paths.list[i].x == x && paths.list[i].y == y){
nodeAtPos = paths.list[i];
return false;
}
return true;
});
return nodeAtPos;
}
return paths.list[id];
}
function deleteNode(x,y){
var obj = getNode(x,y);
//need to delete obejct and delete key references in other objects that were connected to it
}
deleteNode(5,12);
The end result would look like this in my data structure:
[
{"id":0,"x":1,"y":2, "linksTo":[1]},
{"id":1,"x":3,"y":4, "linksTo":[0,2,3]},
{"id":2,"x":5,"y":6, "linksTo":[1]}, //changed
{"id":3,"x":3,"y":10,"linksTo":[1]}, //changed
]
But as you can see in my data strucutre, if I simply delete it, I still have a few nodes that linksTo to it that I need to clean up. Otherwise they will be linked to non existant nodes.
What would be the simplest way to do this?
You could iterate each object and do the following operations:
Check if the node has its link to it. If so remove it from its
linkTo.
During the iteration, keep track of the index of the node which has
its id as the node to be deleted.
Once the iteration is done, remove the node from the array.
Code:
var x = [
{"id":0,"x":1,"y":2, "linksTo":[1]},
{"id":1,"x":3,"y":4, "linksTo":[0,2,3]},
{"id":2,"x":5,"y":6, "linksTo":[1,4]},
{"id":3,"x":3,"y":10,"linksTo":[1,4]},
{"id":4,"x":5,"y":12,"linksTo":[2,3]}
];
var index = -1;
var toDel = 2;
for(var i=0;i<x.length;i++){
if(x[i]["linksTo"].indexOf(toDel) != -1){
x[i]["linksTo"].splice(x[i]["linksTo"].indexOf(toDel),1);
}
if(x[i]["id"] == toDel){index = i;}
}
if(index != -1){
x.splice(index, 1);
}
console.log(x);
There is no other way, but to update the linksTo value for the rest of elements
var deletedId = 4;
var arr = [
{"id":0,"x":1,"y":2, "linksTo":[1]},
{"id":1,"x":3,"y":4, "linksTo":[0,2,3]},
{"id":2,"x":5,"y":6, "linksTo":[1,4]},
{"id":3,"x":3,"y":10,"linksTo":[1,4]},
];
for (var i=0 ; i < arr.length ; i++ ) {
var node = arr[i];
var newRef = [];
for (var l=0 ; l < node.linksTo.length; l++) { // l is an index for links
if (node.linksTo[l] != deletedId)
newRef.push(node.linksTo[l])
}
node.linksTo = newRef; // assign new array
}
Related
I am reading the values from localStorage as nested array and based on some conditions, I am deleting few arrays from the read array. To delete the arrays from master array, I am using the following function:
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
The resultant array is smaller than the original nested array. The following is my original array from localStorage:
var arr = `"["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",270,399,387,397,390,472,"STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",270,399,387,397,390,472,"STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",321,322,414,333,418,375]"`
//Function to drop rectangles
function dropRects() {
dragging = false;
mLocation = getCanvasCoordinates(event);
var a = Math.floor(mLocation.x);
var b = Math.floor(mLocation.y);
var clickedImg = localStorage.getItem('clickedImage');
var arr = new Array();
var getCoords = getArray();
if (typeof getCoords !== 'undefined' && getCoords.length > 0) {
var allCoords = fourthCoord(getCoords);
arr = multiDimensionalUnique(allCoords);
the example array arr given above is the result of `multiDimensionalUnique(allCoords);
var results = new Array();
//For each item in array, perform calculation to find the array that needs to be deleted and store the found array in results - This is working properly
arr.forEach(function(d) {
if (d[0] === clickedImg && d[3] < a && d[4] < b && d[5] > a && d[6] < b && d[7] > a && d[8] > b && d[9] < a && d[10] > b) {
results.push(d)
}
});
//delete the found array from master array.
var newArr;
newArr = arr.diff(results);
//Delete the empty array [] from the master array
var secArr;
secArr = newArr.filter(function(x) { return (x !== (undefined || null || ''));})
//Delete the last two elements from each array, so that it is exactly the same as array downloaded from localStorage
for (var i = 0;i < secArr.length; i++) {
secArr[i].splice(9,2);
}
secArr = JSON.stringify(secArr)
console.log(secArr);
}
localStorage.setItem('coords', secArr);
}
The console.log(secArr) prints the following result (new array):
[["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","FBB",270,406,377,396,381,469],["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",326,321,425,332,420,375],["STAR_SPORTS_2-20170924-200043-210917-00143.jpg","PerimeterBoard","Gillette",367,323,492,330,492,378]]
I am not sure why I have an extra square bracket at the beginning and at the end of this array. (pardon me if this result is different from the example data given above, as this is from my live dashboard)
And the line localStorage.setItem('coords', secArr) resets the localStorage with the new values which looks like this:
"[["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","FBB",270,406,377,396,381,469],["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",326,321,425,332,420,375],["STAR_SPORTS_2-20170924-200043-210917-00143.jpg","PerimeterBoard","Gillette",367,323,492,330,492,378]]"
again with preceeding and succeeding square brackets.
Since the new array is nested within another array, when I read the localStorage again, I am not able to retrieve the array. How do I post secArr variable into localStorage as my original coords variable.
I suspect your answer is due to the double quotes in the var arr declaration. Please look at the following code:
arr = ["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",270,399,387,397,390,472,"STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",270,399,387,397,390,472,"STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",321,322,414,333,418,375];
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
clickedImg = true;
var results = new Array();
//For each item in array, perform calculation to find the array that needs to be deleted and store the found array in results - This is working properly
arr.forEach(function(d) {
if (d[0] === clickedImg && d[3] < a && d[4] < b && d[5] > a && d[6] < b && d[7] > a && d[8] > b && d[9] < a && d[10] > b) {
results.push(d)
}
});
//delete the found array from master array.
var newArr;
newArr = arr.diff(results);
//Delete the empty array [] from the master array
var secArr;
secArr = newArr.filter(function(x) { return (x !== (undefined || null || ''));})
//Delete the last two elements from each array, so that it is exactly the same as array downloaded from localStorage
for (var i = 0;i < secArr.length; i++) {
secArr[i].splice(9,2);
}
secArr = JSON.stringify(secArr)
console.log(secArr);
It produces
["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","FBB",270,406,377,396,381,469],["STAR_SPORTS_2-20170924-200043-210917-00142.jpg","PerimeterBoard","Gillette",326,321,425,332,420,375],["STAR_SPORTS_2-20170924-200043-210917-00143.jpg","PerimeterBoard","Gillette",367,323,492,330,492,378] (notice no array within array).
I have prototypes to recreate how array methods work, pop/push/shift/etc, and I would like to extend the functionality to do the following:
Push/Pop/shift/unshift multiple values
array.push(0);
array.push(1);
array.push(2);
expect(array.pop()).to.be(2);
expect(array.pop()).to.be(1);
expect(array.pop()).to.be(0);
Push/Pop/unshift/etc single values
array.push(0);
array.push(1);
expect([0,1]);
array.pop(1);
expect([0]);
My assumption is that I would need a global array variable to store the elements. Is that the right?
Here is my code:
var mainArray = []; // array no longer destroyed after fn() runs
function YourArray(value) {
this.arr = mainArray; // looks to global for elements | function?
this.index = 0;
var l = mainArray.length;
if(this.arr === 'undefined')
mainArray += value; // add value if array is empty
else
for(var i = 0; i < l ; i++) // check array length
mainArray += mainArray[i] = value; // create array index & val
return this.arr;
}
YourArray.prototype.push = function( value ) {
this.arr[ this.index++ ] = value;
return this;
};
YourArray.prototype.pop = function( value ) {
this.arr[ this.index-- ] = value;
return this;
};
var arr = new YourArray();
arr.push(2);
console.log(mainArray);
My assumption is that I would need a global array variable to store
the elements. Is that the right?
No. That is not right.
You want each array object to have its own, independent set of data. Otherwise, how can you have multiple arrays in your program?
function YourArray(value) {
this.arr = []; // This is the data belonging to this instance.
this.index = 0;
if(typeof(value) != 'undefined')) {
this.arr = [value];
this.index = 1;
}
}
////////////////////////////////////
// Add prototype methods here
///////////////////////////////////
var array1 = new YourArray();
var array2 = new YourArray();
array1.push(2);
array1.push(4);
array2.push(3);
array2.push(9);
// Demonstrate that the values of one array
// are unaffected by the values of a different array
expect(array1.pop()).to.be(4);
expect(array2.pop()).to.be(9);
It's a bit late for this party, admitted but it nagged me. Is there no easy (for some larger values of "easy") way to do it in one global array?
The standard array functions work as in the following rough(!) sketch:
function AnotherArray() {
this.arr = [];
// points to end of array
this.index = 0;
if(arguments.length > 0) {
for(var i=0;i<arguments.length;i++){
// adapt if you want deep copies of objects
// and/or take a given array's elements as
// individual elements
this.arr[i] = arguments[i];
this.index++;
}
}
}
AnotherArray.prototype.push = function() {
// checks and balances ommitted
for(var i=0;i<arguments.length;i++){
this.arr[ this.index++ ] = arguments[i];
}
return this;
};
AnotherArray.prototype.pop = function() {
this.index--;
return this;
};
AnotherArray.prototype.unshift = function() {
// checks and balances ommitted
var tmp = [];
var alen = arguments.length;
for(var i=0;i<this.index;i++){
tmp[i] = this.arr[i];
}
for(var i=0;i<alen;i++){
this.arr[i] = arguments[i];
this.index++;
}
for(var i=0;i<tmp.length + alen;i++){
this.arr[i + alen] = tmp[i];
}
return this;
};
AnotherArray.prototype.shift = function() {
var tmp = [];
for(var i=1;i<this.index;i++){
tmp[i - 1] = this.arr[i];
}
this.arr = tmp;
this.index--;
return this;
};
AnotherArray.prototype.isAnotherArray = function() {
return true;
}
AnotherArray.prototype.clear = function() {
this.arr = [];
this.index = 0;
}
AnotherArray.prototype.fill = function(value,length) {
var len = 0;
if(arguments.length > 1)
len = length;
for(var i=0;i<this.index + len;i++){
this.arr[i] = value;
}
if(len != 0)
this.index += len;
return this;
}
// to simplify this example
AnotherArray.prototype.toString = function() {
var delimiter = arguments.length > 0 ? arguments[0] : ",";
var output = "";
for(var i=0;i<this.index;i++){
output += this.arr[i];
if(i < this.index - 1)
output += delimiter;
}
return output;
}
var yaa = new AnotherArray(1,2,3);
yaa.toString(); // 1,2,3
yaa.push(4,5,6).toString(); // 1,2,3,4,5,6
yaa.pop().toString(); // 1,2,3,4,5
yaa.unshift(-1,0).toString(); // -1,0,1,2,3,4,5
yaa.shift().toString(); // 0,1,2,3,4,5
var yaa2 = new AnotherArray();
yaa2.fill(1,10).toString(); // 1,1,1,1,1,1,1,1,1,1
Quite simple and forward and took only about 20 minutes to write (yes, I'm a slow typist). I would exchange the native JavaScript array in this.arr with a double-linked list if the content can be arbitrary JavaScript objects which would make shift and unshift a bit less memory hungry but that is obviously more complex and slower, too.
But to the main problem, the global array. If we want to use several individual chunks of the same array we need to have information about the starts and ends of the individual parts. Example:
var globalArray = [];
var globalIndex = [[0,0]];
function YetAnotherArry(){
// starts at the end of the last one
this.start = globalIndex[globalIndex.length-1][1];
this.index = this.start;
// position of the information in the global index
this.pos = globalIndex.length;
globalIndex[globalIndex.length] = [this.start,this.index];
}
So far, so well. We can handle the first array without any problems. We can even make a second one but the moment the first one wants to expand its array we get in trouble: there is no space for that. The start of the second array is the end of the first one, without any gap.
One simple solution is to use an array of arrays
globalArray = [
["first subarray"],
["second subarray"],
...
];
We can than reuse what we already wrote in that case
var globalArray = [];
function YetAnotherArray(){
// open a new array
globalArray[globalArray.length] = [];
// point to that array
this.arr = globalArray[globalArray.length - 1];
this.index = 0;
}
YetAnotherArray.prototype.push = function() {
for(var i=0;i<arguments.length;i++){
this.arr[ this.index++ ] = arguments[i];
}
return this;
};
// and so on
But for every new YetAnotherArray you add another array to the global array pool and every array you abandon is still there and uses memory. You need to manage your arrays and delete every YetAnotherArray you don't need anymore and you have to delete it fully to allow the GC to do its thing.
That will leave nothing but gaps in the global array. You can leave it as it is but if you want to use and delete thousands you are left with a very sparse global array at the end. Or you can clean up. Problem:
var globalArray = [];
function YetAnotherArray(){
// add a new subarray to the end of the global array
globalArray[globalArray.length] = [];
this.arr = globalArray[globalArray.length - 1];
this.index = 0;
this.pos = globalArray.length - 1;
}
YetAnotherArray.prototype.push = function() {
for(var i=0;i<arguments.length;i++){
this.arr[ this.index++ ] = arguments[i];
}
return this;
};
YetAnotherArray.prototype.toString = function() {
var delimiter = arguments.length > 0 ? arguments[0] : ",";
var output = "";
for(var i=0;i<this.index;i++){
output += this.arr[i];
if(i < this.index - 1)
output += delimiter;
}
return output;
}
// we need a method to delete an instance
YetAnotherArray.prototype.clear = function() {
globalArray[this.pos] = null;
this.arr = null;
this.index = null;
};
YetAnotherArray.delete = function(arr){
arr.clear();
delete(arr);
};
// probably won't work, just a hint in case of asynch. use
var mutex = false;
YetAnotherArray.gc = function() {
var glen, indexof, next_index, sub_len;
indexof = function(arr,start){
for(var i = start;i<arr.length;i++){
if (arr[i] == null || arr[i] == undefined)
return i;
}
return -1;
};
mutex = true;
glen = globalArray.length;
sublen = 0;
for(var i = 0;i<glen;i++){
if(globalArray[i] == null || globalArray[i] == undefined){
next_index = indexof(globalArray,i);
if(next_index == -1){
break;
}
else {
globalArray[i] = globalArray[next_index + 1];
globalArray[next_index + 1] = null;
sublen++;
}
}
}
globalArray.length -= sublen - 1;
mutex = false;
};
var yaa_1 = new YetAnotherArray();
var yaa_2 = new YetAnotherArray();
var yaa_3 = new YetAnotherArray();
var yaa_4 = new YetAnotherArray();
yaa_1.push(1,2,3,4,5,6,7,8,9).toString(); // 1,2,3,4,5,6,7,8,9
yaa_2.push(11,12,13,14,15,16).toString(); // 11,12,13,14,15,16
yaa_3.push(21,22,23,24,25,26,27,28,29).toString();// 21,22,23,24,25,26,27,28,29
yaa_4.push(311,312,313,314,315,316).toString(); // 311,312,313,314,315,316
globalArray.join("\n");
/*
1,2,3,4,5,6,7,8,9
11,12,13,14,15,16
21,22,23,24,25,26,27,28,29
311,312,313,314,315,316
*/
YetAnotherArray.delete(yaa_2);
globalArray.join("\n");
/*
1,2,3,4,5,6,7,8,9
21,22,23,24,25,26,27,28,29
311,312,313,314,315,316
*/
YetAnotherArray.gc();
globalArray.join("\n");
/*
1,2,3,4,5,6,7,8,9
21,22,23,24,25,26,27,28,29
311,312,313,314,315,316
*/
But, as you might have guessed already: it doesn't work.
YetAnotherArray.delete(yaa_3); // yaa_3 was 21,22,23,24,25,26,27,28,29
globalArray.join("\n");
/*
1,2,3,4,5,6,7,8,9
21,22,23,24,25,26,27,28,29
*/
We would need another array to keep all positions. Actual implementation as an exercise for the reader but if you want to implement a JavaScript like array, that is for arbitrary content you really, really, really should use a doubly-linked list. Or a b-tree. A b+-tree maybe?
Oh, btw: yes, you can do it quite easily with a {key:value} object, but that would have squeezed all the fun out of the job, wouldn't it? ;-)
I have two node lists, one of <a> elements and another one of <img> elements. The size of those node list is different.
I have added an attribute to each of those nodes called score. Right now I have a method that does this:
getImageWithBiggestScore: function(images,anchor_images) {
var best_scored_image = images[0];
for (var i = 1; i < images.length; i++) {
if (images[i].score > best_scored_image.score) {
best_scored_image = images[i];
}
}
for (var i = 0; i < anchor_images.length; i++) {
if (anchor_images[i].score > best_scored_image.score) {
best_scored_image = anchor_images[i];
}
}
return best_scored_image;
},
And this returns the node with the biggest score. However, I would like to get the 3 nodes (or 5,6... Ideally it would be a parameter of the function) with the biggest scores. How can I do that?
If i got this right, you can do the following ...
HTML
<ul id='x'>
<li data-score='1'></li>
<li data-score='44'></li>
<li data-score='2'></li>
<li data-score='10'></li>
</ul>
<ul id='y'>
<li data-score='9'></li>
<li data-score='1'></li>
<li data-score='1'></li>
<li data-score='3'></li>
</ul>
Javascript
var x = Array.prototype.slice.call(document.getElementById('x').children), // images
y = Array.prototype.slice.call(document.getElementById('y').children), // anchor_images
z = [], // array that will keep the results
param = 4, // number of nodes as a parameter
sortFunc = function(a, b) {
if(typeof a === 'object' && typeof b === 'object')
return (b.getAttribute('data-score') * 1) - (a.getAttribute('data-score') * 1);
}; // sort desc
x.sort(sortFunc); // order the first array desc
y.sort(sortFunc); // order the second array desc
// push into z the highest values of each array
for(var i = 0; i < param; i++) {
z.push(x[i]);
z.push(y[i]);
}
// now, z contains the combination of the highest values from x and y
z.sort(sortFunc); // sort desc the new array
z = z.splice(0, param); // get the result :)
var result = "";
for(var i = 0; i < z.length; i++) {
result += z[i].getAttribute('data-score') + ",";
}
document.getElementById('result').innerHTML = result;
You may need to adapt to get this working with something specific to your code ...
The code in action: http://jsfiddle.net/YHjgY/5/
I would use the recursion probably here
the recursion function would be something like this
var arrObjs = new Array();
arrObjs.push("a elements arr obj"); // pushes the complete array of a elements to the first index of arrObjs
arrObjs.push("div elements arr obj"); //
var value = run(0,0);
function run (index,biggestScore){
var arr = new Arrray();
var smallestLength = 999; // could probably write this a better way. Assuming the length would not be more than 999 length
for(var i=0; i < arrObjs.length;i++){
if(arrObjs[i].length >= index){
if((arrObjs[i].length-index) < smallestLength){
smallestLength = arrObjs[i].length
}
arr.push(arrObjs[i]);
}
}
for(var j=0; j < arr.length;j++){
for(var k=index; k<arr[j].length;k++){
if(arr[j][k].score>biggestScore){
biggestScore.score = arr[j][k];
}
}
}
biggestScore = run(smallestLength,biggestScore);
return biggestScore;
}
There could be a few errors. Didn't test it; I guess you understood the basic idea behind it. Let me know if you have any questions :)
Is there a simpler (or more efficient) way of achieving the following:
var _dataObjects = [{id:0, data:"data0", nextID:1},
{id:1, data:"data1", nextID:2},
{id:2, data:"data2", nextID:3} .. etc.];
generateNextPieceOfData();
function generateNextPieceOfData(){
var len = _dataObjects.length;
for ( var i = 0; i < len; i ++ ) {
var nextDataID = _dataObjects[i].nextID;
var nextData;
for ( var j = 0; j < len; j ++ ) {
if( _dataObjects[j].id == nextDataID ){
nextData = _dataObjects[j].data;
break;
}
}
}
}
The above example is abstracted from the problem I'm having and I realise the ID numbers are sequential in this instance but in the real problem nextID numbers do not run sequentially.
Thanks in advance.
Use the right data structure for your problem. Since you want to find an object by ID, create a hash map with the IDs as keys and objects as values:
var object_map = {};
for(var i = 0, l = _dataObjects.length; i < l; i++) {
objects[_dataObjects[i].id] = _dataObjects[i];
}
Then getting the next object is simply:
var next_object = object_map[someObject.nextID];
You still have iterate until some terminal condition is met though. For example:
function generatePath(id_a, id_b) {
var obj = object_map[id_a];
var path = [obj];
while (obj && obj.id !== id_b) {
obj = object_map[obj.nextID];
path.push(obj);
}
return path;
}
If your code works sequentially only, then you can sort the items by id or whatever and your code should work right? Try this:
_dataObjects = _dataObjects.sort(function(a, b) {
return a.id > b.id;
});
I need to read all the connection times. (connectionTimes)
I need to delete the line - when it will be offline more than online:
userId: 1,
connectionTimes:
[
{onlineTime:"11:10:30", offlineTime:"11:18:12"}, //delete
{onlineTime:"11:14:14", offlineTime:"11:52:41"} //delete
]
Delete user id - When times the connection will be empty.
userId: 1, //delete userid
connectionTimes:
[
//empty connection
]
I have this data structure:
var users = [];
users[0] = {
userId: 1,
connectionTimes:
[
{onlineTime:"11:10:30", offlineTime:"11:18:12"},
{onlineTime:"11:14:14", offlineTime:"11:52:41"}
]
}
users[1] = {
userId: 2,
connectionTimes:
[
{onlineTime:"8:08:14", offlineTime:"1:15:00"}
]
}
You can delete a property from an JavaScript object with the delete operator:
var sampleObject = {
"key1": "value1",
"key2": "value"
};
delete sampleObject["key2"];
or like this:
delete sampleObject.key2
See the Mozilla Developer Network JavaScript Reference for more background on the delete operator:
https://developer.mozilla.org/en/JavaScript/Reference/Operators/delete
Your specific example would look something like this:
for(var id in users) {
var user = users[id];
if (user.connectionTimes.length === 0) {
delete users[id];
break
}
for(var i=0; i<=user.connectionTimes.length; i++) {
var connectionTime = user.connectionTimes[i];
if (connectionTime.onlineTime < connectionTime.offlineTime) {
delete users[id];
break;
}
}
}
Here is a link to jsFiddle showing the code in action:
http://jsfiddle.net/Q86Jd/
There are many ways to remove things from arrays in Javascript. The mains ones I can think of are
The delete operator. Using it sets the chosen position to undefined and is similar to just setting the element to null. (The main difference is that deleting a key will cause it to be skiped when iterating with the forEach and map array methods).
var xs = [0,1,2];
delete xs[1];
console.log(xs); // [0, undefined, 2]
The splice method can remove a chunk or the array, moving the remaining elements left to fill it in.
var xs = [0,1,2,3];
xs.splice(2, 1); //index, ammount to remove
console.log(xs); // [0,1,3]
Setting the array's length property truncates it. This can be used to manually remove elements the old fashioned way when you want more control.
var xs = [0,1,2,3];
xs.length = 2;
console.log(xs); // [0,1]
xs.length = 4;
console.log(xs); // [0,1, undefined, undefined]
So in your case we might do something like this:
function filter_in_place(array, predicate){
var j=0;
for(var i=0; i<arr.length; i++){
var x = arr[i];
if(pred(x)){
arr[j++] = x;
}
}
arr.length = j;
}
for(var i=0; i < users.length; i++){
filter_in_place( users[i].connections, function(conn){
/*return if offline larger then online*/
});
}
filter_in_place(users, function(user){ return user.connections.length > 0; });
Basically you want to use something like this:
for( var i=0; i<users.length; i++) {
for( var j=0; j<users[i].connectionTimes.length; j++) {
if( users[i].connectionTimes[j].onlineTime < users[i].connectionTimes[j].offlineTime) {
delete users[i].connectionTimes[j];
j--;
}
}
if( users[i].connectionTimes.length == 0) {
delete users[i];
i--;
}
}
This is pretty straightforward. In pseudocode:
declare user, times
for each index in users
set user = users[ index ]
set times = user.connectionTimes
if times is empty
then delete users[ index ]
else
declare onlineSecs, offlineSecs
for each index2 in times
set onlineSecs = timeInSeconds( times[ index2 ].onlineTime )
set offlineSecs = timeInSeconds( times[ index2 ].offlineTime )
if offlineSecs > onlineSecs
then delete times[ index2 ]
In JavaScript the command to delete a variable is delete and can be used on arrays the same, e.g. delete someArray[ someIdx ];. The implementation of timeInSeconds will be something like this:
function timeInSeconds( timeWithColons ) {
var hrsMinsSecs = "12:34:56".split(':');
return ( parseInt( hrsMinsSecs[0] ) * 60 +
parseInt( hrsMinsSecs[1] )
) * 60 +
parseInt( hrsMinsSecs[2] )
;
}