Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript splice is breaking on jQuery .each()?

var results = ['one', 'two', 'one hundred', 'three'];
var removal = [];
$.each(results, function(i) {
    removal.push(i);
    if (results[i].indexOf('one') == -1){
        console.log('Removing:' + results[i] + '(' + removal[i] + ')');
        results = results.splice(removal[i], 1);
    }
});

I have the following code, but it is breaking after it removes the first result.

I want it to remove anything that does not contain the word 'one'.

I am guessing it is breaking because the removal order changes once one has been removed.

What am I doing wrong?

like image 871
pdlol Avatar asked Feb 02 '12 00:02

pdlol


People also ask

How break out of jquery each?

To break a $. each or $(selector). each loop, you have to return false in the loop callback. Returning true skips to the next iteration, equivalent to a continue in a normal loop.

Why is splice not working on array?

It's not working because you are removing items from the array while looping through the keys. When you remove an item, it will rearrange the other items depending on how the array is implemented internally, and you end up with a loop that doesn't iterate over the keys that you expect.

What is one difference between the splice () and slice () methods?

The splice() method returns the removed items in an array. The slice() method returns the selected element(s) in an array, as a new array object. The splice() method changes the original array and slice() method doesn't change the original array.

What is the function of splice () in Javascript?

The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.


3 Answers

You shouldn't splice the Array while you're iterating it with $.each().

Since you're changing the length of the Array, you're going beyond the final index since.

Just use a for loop and adjust i when you remove an item...

var results = ['one', 'two', 'one hundred', 'three'];
var removal = [];
for(var i = 0; i < results.length; i++) {
    removal.push(i);
    if (results[i].indexOf('one') == -1){
        console.log('Removing:' + results[i] + '(' + removal[i] + ')');
        results.splice(i, 1);
        i--;
    }
};

Note that I changed this...

results = results.splice(removal[i], 1);

to this...

results.splice(removal[i], 1);

You don't want that since splice() modifies the original, and returns the item(s) removed.

like image 73
3 revsuser1106925 Avatar answered Oct 04 '22 17:10

3 revsuser1106925


var myArr = [0,1,2,3,4,5,6];

Problem statement:

myArr.splice(2,1);

  \\ [0, 1, 3, 4, 5, 6];

now 3 moves at second position and length is reduced by 1 which creates problem.

Solution: A simple solution would be iterating in reverse direction when splicing.

var i = myArr.length;
while (i--) {
    console.log(myArr);
    myArr.splice(i,1);
}

Output:

[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4]
[0, 1, 2, 3]
[0, 1, 2]
[0, 1]
[0]
like image 35
Arun Pratap Singh Avatar answered Oct 04 '22 18:10

Arun Pratap Singh


The problem is that the $.each() function iterates through the array in order from the first element, and internally it sets the index range it will be using at the beginning. So when you remove items from that array it doesn't know you've done so.

You can easily work around this by using a standard for statement. If you loop backwards from the end of the list through to the beginning you can remove items without affecting the loop. If you loop forwards you need to adjust the loop counter each time you remove an item from the array.

like image 45
nnnnnn Avatar answered Oct 04 '22 16:10

nnnnnn