Working on app where speed is crucial, the arrays are huge and the objects contained within the arrays.
I experimented with grep and filter and can not see significant speed difference, varies +- 5ms , also tried looping through array and using .splice(i,1); (same results).
I have a fast machine, if it always take more or less the same time on fast machine, does that mean it will take more or less same time on older machine?
Is there faster way to remove an object from array?
Want to do something like this:
var filterTime = performance.now();
doStuff1();
var filterTimeEnd = performance.now();
var grepTime = performance.now();
doStuff2();
var grepTimeEnd = performance.now();
and then store the differences in cookie, so the next time the page loads or is refreshed, execute most efficient way: removing object from array.
UPDATE
snippet of filter experiment
companyMasters = companyMasters.filter(function (obj) {
return obj.masterId != CompanyObj.masterId;
});
3 Answers 3
The existing answer already provide good solutions to reducing the runtime complexity of the underlying problem.
However I want to briefly answer the original question as well, since this is the first page when googling for how to remove from an array the most performant way.
Without maintaining order the fastest way to remove by index is removing by assigning the last element to the to be removed index and popping from the array, since this has O(1) runtime complexity.
Array.prototype.mySwapDelete = function arrayMySwapDelete (index) {
this[index] = this[this.length - 1];
this.pop();
}
With maintaining order the fastest way to remove by index is shifting in place:
Array.prototype.myShiftDelete = function arrayMyShiftDelete (index) {
var stop = this.length - 1;
while (index < stop) {
this[index] = this[++index];
}
this.pop();
}
I have created a JS perf snippet to benchmark the different functions: https://jsperf.com/array-remove-by-index
When wanting to filter, it is also significantly faster to filter in place and shift than calling the native .filter() function, which allocates a new array. This in place filter also maintains order:
Array.prototype.myShiftFilter = function arrayMyShiftFilter (predicate) {
let i, j;
for (i = 0, j = 0; i < this.length; ++i) {
if (predicate(this[i])) {
this[j] = this[i];
++j;
}
}
while (j < this.length) {
this.pop();
}
}
See also JS Perf snippet for benchmark: https://jsperf.com/array-filter-in-place
6 Comments
this[index] = this.pop()Any solution in which you need to iterate the array to find a single item would seem to indicate that you have a problem with the data structure you are using. Rather than storing your objects in a numerically indexed array, perhaps your should be storing them in an object where keys are the masterId values that you are going to be trying to do lookups against. At a very minimum, if you need to keep your objects in a numerically index array for some other reason, you could consider building a separate object within which you map the masterId values to the index in the main array where the object resides.
So rather than something like this:
[
{
masterId: 'foo',
...
},
{
masterId: 'bar',
...
},
...
]
You would build your data structure like this:
{
foo: {
masterId: 'foo',
...
},
bar: {
masterId: 'bar',
...
},
...
}
This would allow your code to look like this:
var needle = CompanyObj.masterId;
// delete object set for 'needle' property
delete companyMaster[needle];
This gives you an operation with O(1) time complexity instead of O(n).
5 Comments
O(n) operation). If you are only going to delete one item from the array, you won't really gain much value. But if you have to delete multiple values, you will likely still see benefit. Either way, if you are needing to loop the array for lookup, you should build in a break to bail out of the loop when a match is found, so you don't have to loop the entire array.Instead of looping through the array over and over to remove one item at a time, build a map that you can use to filter out all the items at once:
var map = {};
for (var i = 0; i < itemsToRemove.length; i++) {
map[itemsToRemove[i]] = 1;
}
companyMasters = companyMasters.filter(function (obj) {
return !(obj.masterId in map);
});
1 Comment
Explore related questions
See similar questions with these tags.
delete objects.objectIdwhich should be fast as lightning.