Reputation: 348
I have an multidimensional array
[{id:0, type:1}, {id:1, type:1}, {id:2, type:2}]
What I aim to do is to remove all type 1 and so the desired result should leave id:2, type:2
tmpType = 1;
for (var i in arr) {
if(arr[i].type == tmpType) {
arr.splice(i, 1);
}
}
However in the loop, from what I understand it will loop thrice but everytime I splice, the loop differs. This is the result I am getting.
{{id:1, type:1}, {id:2, type:2}}
If i have 3 kinds of type:1, I will always have the last one still in the array.
Upvotes: 2
Views: 14061
Reputation: 66304
As splice
changes the length you either need to move your iterator or iterate downwards.
You should also be using for
, not for..in
to iterate over an Array
var arr = [{id:0, type:1}, {id:1, type:1}, {id:2, type:2}];
var type = 1,
i; // OR // i = arr.length;
for (i = arr.length - 1; i >= 0; --i) { // while (i-- > 0) {
if (arr[i].type == type) {
arr.splice(i, 1);
}
}
arr; // [{"id": 2, "type": 2}]
Other answers suggest using a the filter method of Arrays which is a great alternative option and you may find it cleaner. However, please be aware the result of these two ways are slightly different as this way will modify the original Array reference ("has side effects"), whereas the filter method will create an entirely new instance of Array and leave the original untouched.
You can think of filter like this, which also shows why it's a bit expensive
function filter(arr, test) {
var i,
arr_out = [];
for (i = 0; i < arr.length; ++i)
if (i in arr && test(arr[i]) // invoking test each time is expensive
arr_out.push(arr[i]);
return arr_out;
}
splice
can be expensive too, however, as you are moving all the indicies around.
The least expensive way to do this without side effects (i.e. original left alone) is to do a mix of the two; a manual for
loop which push
es to a new Array with out test written into it, not invoked seperately
// arr as before
var arr2 = [],
i;
for (i = 0; i < arr.length; ++i)
if (arr[i].type === type) // doing our test directly, much cheaper
arr2.push(arr[i]);
arr2; // desired array
For a original modified, easiest option is to use the splice
method I wrote at the start of this answer.
The other option is to copy the original, var arr2 = arr.slice()
, then empty the original, arr.length = 0;
, then do the last loop I showed except with arr
and arr2
swapped around to re-populate arr
Upvotes: 3
Reputation: 5708
Assuming you really meant:
[{id:0, type:1}, {id:1, type:1}, {id:2, type:2}]
You can use filter
:
var oldArr = [{id:0, type:1}, {id:1, type:1}, {id:2, type:2}];
var newArr = oldArr.filter(function(obj) {
return obj.type !== 1;
});
Upvotes: 1
Reputation: 13922
You should loop backwards through the array. Using splice looping forwards will mean that you'll skip past the element after the one you splice on each iteration, now that it has the same index as the one you removed.
var arr = [{id: 0, type: 1}, {id: 1, type: 1}, {id: 2, type: 2}];
for (var i = arr.length; i--;) {
if (arr[i].type === 1) arr.splice(i, 1);
}
You could also do this:
var arr = [{id: 0, type: 1}, {id: 1, type: 1}, {id: 2, type: 2}];
arr = arr.filter(function (obj) {
return obj.type !== 1;
});
Upvotes: 1
Reputation: 39649
You should probably just use .filter()
for this:
var arr = [{id:0, type:1}, {id:1, type:1}, {id:2, type:2}];
var filtered = arr.filter(function(item) {
return item.type !== 1;
});
Demo: http://jsbin.com/tafuhasoti/edit?js,console
Upvotes: 3
Reputation: 1300
Assuming you have an actual array.
var data = [{id:0, type:1}, {id:1, type:1}, {id:2, type:2}]
//Array has a method filter
var filterdata = data.filter(function(element, index, array){
return element.type == 2;
})
//filterdata will contain an array of only objects that have type 2
Upvotes: 1