javascript : after calling the splice() control comes out from the loop - javascript

I have an array rosters and i want to alter this array according to some conditions. Here what I'm trying to do.
somefunction(callback) {
for (var i in this.rosters) {
var roster = this.rosters[i];
if (roster.age > 7200) {
this.rosters.splice(i, 1);
} else {
this.rosters[i].age = this.EMarshal.tu.getAgeOfTime(
this.EMarshal.tu.getMyTime(
this.EMarshal.tu.getMyDate(roster.date), roster.shifttime
)
);
console.log(this.rosters[i].age);
}
}
callback();
}
When the the if condition is true and splice is been called, control comes out of from loop and call callback(). But i want to run the loop for each values in the array.
plz carefully notice that there are rosters and roster 2 different variables.
Any idea why its happening and the solution will be usefull.
Thanks

It's just because you are trying to alter the array on which you are iterating.
So, just ad some logic to store the indexes as you have said you have tried.
Here is one suggestion
before getting into loop var index = [];
then your if condition
if (roster.age > 7200) {
index.push(i);
}
and then after the loop, remove those indexes from rosters
for (var j = index.length - 1; j > -1; j-- ) {
console.log(j);
this.rosters.splice(index[j], 1);
}
Remember to iterate the index from last index otherwise you will remove the 1st index and the trying to remove the last index from the rosters, but now you have removed the element from the array so the length is been changed.

Related

Delete value from array object in javascript (jquery)

I am trying to delete objects from my array via javascript. Im building a simple mobile jquery application and want to delete items from an array. I use the following code. I have a list with checkboxes in it. Every checkbox has a value that belongs to the list item. So when multiple checkboxes are checked.. it should delete all these objects (items) from the array.
function deleteFunction()
{
objects = getObjects();
$("input:checked").each(function()
{
var inputValue = $(this).val();
for(i = getObjects().length; i >=0; i--)
{
if('{"title":"'+ inputValue + '"}' == JSON.stringify(objects[i]))
{
objects.splice(i, 1);
return true;
}
}
});
alert(JSON.stringify(objects));
window.location.reload();
}
The annoying thing is as follows:
When i slice the object from the array, the object is restored on the second iteration. So it always removes only 1 object from the array.
To test my output i used the following code within the if statement:
alert(i);
alert(JSON.stringify(objects[i]));
objects.splice(i, 1);
alert(i);
alert(JSON.stringify(objects));
return true;
The output is as follows
1
{"title":"hi2"}
1
[{"title":"hi1"}, {"title":"hi3"}]
2
{"title":"hi3"}
2
[{"title":"hi1"}, {"title":"hi2"}]
so i slice hi2, but has returned
Thanx for answer and respond
Solution Thanx to depperm + indubitablee:
function deleteFunction()
{
var objects = getObjects();
$("input:checked").each(function()
{
var inputValue = $(this).val();
for(i = objects.length -1; i >=0; i--)
{
if(objects[i].title == inputValue)
{
objects.splice(i, 1);
}
}
});
localStorage.setItem("objects", JSON.stringify(objects));
window.location.reload();
}
There are a few things I would change, first in the for loop no need to call getObjects() each time just use objects. Then in the if simply check if the objects[i].title is the same as the inputValue.
function deleteFunction()
{
objects = getObjects();
$("input:checked").each(function()
{
var inputValue = $(this).val();
for(i = objects .length; i >=0; i--)
{
if(objects[i].title==inputValue)
{
objects.splice(i, 1);
}
}
});
alert(JSON.stringify(objects));
window.location.reload();
}
use .splice() instead of .slice().
slice does NOT alter/manipulate the original array at all, it just creates another array based on your selection.
splice does alter the original array.
reference: http://www.devcurry.com/2010/12/slice-and-splice-in-javascript.html
The array method slice does not remove array elements. Use splice instead.
There are some problems with your code:
You missed the keyword var sometimes.
The variable i is equal to the length of the array in the first iteration. It should be one minus that.
Instead of converting to JSON to compare the objects, you could have just compared the value of the title property.

Looping through arrays and checking their values

What I have done is that I have firstly I have parsed them with the jQuery function, $.parseJSON() and so now I am having 2 arrays with 3 objects inside them. What I want to do is that I want to loop over both the arrays at the same time so that I could check the Post_IDs of the current object in the loop of both the arrays that if they are equal or not and then if I find that the Post_ID is not present there already or there is a mismatch then I want to do something.
Here's what I have done:
var posts = <? php echo $posts; ?> ;
setInterval(function () {
$.get("admin/post/get_new_posts.php", {
userId: <? php echo User::GetUserID($_SESSION["username"]); ?>
}, function (data) {
data = $.parseJSON(data);
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < posts.length; j++) {
if (posts[j].Post_ID != data[i].Post_ID) {
//do something...
} else {
}
}
}
});
}, 10000);
The posts variable has its value and I am sure about it by logging them into the console. Now what happens here is that every ten seconds a get request is sent and checks if the Post_ID meets of the posts variable object does not equal the Post_ID of the data variable then do something in there. But that's not the case. The condition is always going true.
And yes, here are my objects. The first one is the posts variable and the second one is the data variable.
Any idea of how can I loop through both the variables or arrays and check for a property at the same time while looping?
You're comparing every entry in posts to every entry in data. Most of those won't match - posts[0] won't match data[1], data[2], etc.
It sounds like you want to look at the corresponding members of each list (posts[0] vs. data[0], etc.)
In that case, you need one loop, not two.
// find the longest array's length
var maxi = Math.max(posts.length, data.length, 0);
for ( var i = 0; i < maxi; ++i )
{
if (i >= posts.length)
{
// an entry in data, but not posts
}
else if (i >= data.length)
{
// an entry in posts, but not data
}
else if (data[i].Post_ID != posts[i].Post_ID)
{
// mismatched IDs
}
else
{
// matched IDs
}
}
You are executing two loops and this creates a problem. because they have the following meaning (I'm gonna translate them into pure english):
for each item of array 'data', check any item in array 'posts' that is not equal to the current item of 'data'. This is why it is always "doing something".
Since both arrays have the same length, you should do one loop like this :
for (var i = 0; i < data.length; i++) {
if (posts[i].Post_ID != data[i].Post_ID) {
//do something...
} else {
}
}

How to keep Javascript array sorted, without sorting it

I have a Node.js application where I have to very often do following things:
- check if particular array already contains certain element
- if element does exist, update it
- if element do not exist, push it to the array and then sort it using underscore _.sortBy
For checking if the element already exists in the array, I use this binary search function:
http://oli.me.uk/2013/06/08/searching-javascript-arrays-with-a-binary-search/
In this way, when the size of the array grows, the sorting becomes slower and slower.
I assume that the array size might grow to max 20 000 items per user. And eventually there will be thousands of users. The array is sorted by a key, which is quite a short string. It can be converted into integer if needed.
So, I would require a better way to keep the array sorted,
in stead of sorting it every time new element is pushed onto it.
So, my question is, how should/could I edit the binary search algorithm I use, to enable me to
get the array index where the new element should be placed, if it doesn't already exist in the array?
Or what other possibilities there would be to achieve this. Of course, I could use some kind of loop that would start from the beginning and go through the array until it would find the place for the new element.
All the data is stored in MongoDB.
In other words, I would like to keep the array sorted without sorting it every time a new element is pushed.
It's easy to modify this binaryIndexOf function to return an index of the next element when no matches found:
function binaryFind(searchElement) {
'use strict';
var minIndex = 0;
var maxIndex = this.length - 1;
var currentIndex;
var currentElement;
while (minIndex <= maxIndex) {
currentIndex = (minIndex + maxIndex) / 2 | 0; // Binary hack. Faster than Math.floor
currentElement = this[currentIndex];
if (currentElement < searchElement) {
minIndex = currentIndex + 1;
}
else if (currentElement > searchElement) {
maxIndex = currentIndex - 1;
}
else {
return { // Modification
found: true,
index: currentIndex
};
}
}
return { // Modification
found: false,
index: currentElement < searchElement ? currentIndex + 1 : currentIndex
};
}
So, now it returns objects like:
{found: false, index: 4}
where index is an index of the found element, or the next one.
So, now insertion of a new element will look like:
var res = binaryFind.call(arr, element);
if (!res.found) arr.splice(res.index, 0, element);
Now you may add binaryFind to Array.prototype along with some helper for adding new elements:
Array.prototype.binaryFind = binaryFind;
Array.prototype.addSorted = function(element) {
var res = this.binaryFind(element);
if (!res.found) this.splice(res.index, 0, element);
}
If your array is already sorted and you want to insert an element, to keep it sorted you need to insert it at a specific place in the array. Luckily arrays have a method that can do that:
Array.prototype.splice
So, once you get the index you need to insert at (you should get by a simple modification to your binary search), you can do:
myArr.splice(myIndex,0,myObj);
// myArr your sorted array
// myIndex the index of the first item larger than the one you want to insert
// myObj the item you want to insert
EDIT: The author of your binary search code has the same idea:
So if you wanted to insert a value and wanted to know where you should
put it, you could run the function and use the returned number to
splice the value into the array.
Source
I know this is an answer to an old question, but the following is very simple using javascripts array.splice().
function inOrder(arr, item) {
/* Insert item into arr keeping low to high order */
let ix = 0;
while (ix < arr.length) {
//console.log('ix',ix);
if (item < arr[ix]) { break; }
ix++;
}
//console.log(' insert:', item, 'at:',ix);
arr.splice(ix,0,item);
return arr
}
The order can be changed to high to low by inverting the test

How to remove some items by iterating over the array of objects?

I want to iterate through the array of object and remove some of them based on some condition.
I used splice for removing the items to preserve an orderly count of items.
Then each time the item removed I would decrease the count.
But for some reason it never works:
var arr=[{img:1},{img:2},{img:3},{img:4}];
for (var i=0, count= arr.length; i < count; ) {
if ( this.arr[i].img==3 ) {
this.arr.splice(i,1);
count--;
}else i++
};
alert(JSON.stringify(arr));
​
...any ideas?
Looping backwards should do the trick. This avoids using counters and resetting the counter when removing an entry due to the "retreating" values.
var i;
for (i = arr.length; i--;) {
if (arr[i].img === 3) {
arr.splice(i, 1);
}
};
Simpler to loop through the array backwards, then you don't have to adjust the iterator:
var i = arr.length;
while ( i-- ) {
if ( arr[i].img == 3 ) {
arr.splice(i,1);
}
}
I have dealt with this same difficulty before. My solution was to loop through the array and compose another array of elements to remove. loop through the list of elements to remove in reverse and remove them. This worked well for me.
Michael G.
You're referring to this.arr instead of just arr.
Delete the two this. from the code, and it works. :-)
try this loop, I haven't tested but should work.
var arr=[{img:1},{img:2},{img:3},{img:4}];
for (var i=arr.length-1; i >= 0; i--) {
if ( arr[i].img==3 ) {
arr.splice(i,1);
}
};
alert(JSON.stringify(arr));

removing of array elements an issue

I have a situation where i add tables on a click of button and each table is stored in array. Now when i remove 2 or 3 tables, wrong index are being removed.
addTable: function (obj) {
for (var i = 0; i < obj.length; i++) {
// Adding of table
array.push(obj)
// delete code of the table
(function (i) {
deleteButton.addEventListener('click', function (e) {
array.splice(i, 1);
});
})(i);
}
}
The problem i am facing is the value of i is always zero. each time i click on the button a the addTable function is called and the counter is always zero and that is passed to the function(i) too.
Any ideas on how can keep track of different i or counter so that it deletes the correct index in the array
Here is an update
this is the sample object i am sending each time.
Each time i click on the Add Table button, the same object is being passed. Now i am having difficulty in keeping track of the index of each item.
Once you've removed one table, all other tables have moved and their indexes that you installed in the delete Buttons will be wrong now. When you remove items from the array, all indexes shift.
So, suppose you remove table 3. Then, you press delete for table 4. It's got an index of 4, but since you already removed table 3, it's in spot 3 in the array now (after the previous delete), not spot 4. But, you're code still has i==4 associated with that table and is trying to delete it here, but it's not there any more.
What you are doing is just not a good way to do this. If you want to expand further on what you're really trying to do, we can help with much better solutions.
Given the limited info we have so far, all I know of to do is to find the item in the array (wherever it might have moved to) and delete it from there.
addTable: function (obj) {
for (var i = 0; i < obj.length; i++) {
// Adding of table
array.push(obj)
// delete code of the table
(function (item) {
deleteButton.addEventListener('click', function (e) {
// search through the array to find where this item is
// and remove it from the array
for (var j = 0; j < array.length; j++) {
if (array[j] === item) {
array.splice(j, 1); // remove it
break;
}
}
});
})(obj);
}
}
I do not know about deleteButton, but in case that obj is array with only one element (length equals 1): [{....}] and array.push is native Array.prototype.push method then:
addTable: function (obj) {
// Adding of table
var index=array.push(obj);
// delete code of the table
deleteButton.addEventListener('click', function (e) { array.splice(index, 1); });
}
if obj.length is undefined i will allways be 0
further more, then i < obj.length return false and the for loop will never execute
if obj passed in is this object:
var addObjectResponse = [{...}];
then addObjectResponse is an array of 1, hence i will allways be 0
i = 0
obj.length = 1
i < obj.length => 0 < 1 => true once

Categories

Resources