Deleting Array Element in js? - javascript

As array in js are objects but deleting an array element has BigO O(n) whereas deleting an obj element has BigO O(1) ? Why ?
Pls let me know where i am doing wrong !
Thanks

This not an obvious question. In object this is more clearer because delete operator has constant time of complexity, because you are deleting specific property or method and don't iterate over the object.
Array is an object with ordered indexes and we are using for deletion method which iterating over array and delete item such as Array.prototype.splice():
let arr = [1,6,10,99,44]; //If you want delete 10 you have to iterate by 1,6 and 10
arr.splice(2,1); //arr = [1,6,99,44]
And above we have linear time of complexity (BigO(n)), but we can achieve a constant time for deletion item from array:
let arr = [1,6,10,99,44]; //If you want delete last item
arr.length = 4 //arr = [1,6,10,66]
Finally one tip, never use delete operator for array, such as delete arr[2], because length of the array is not changed and you get an array [1,6, empty,99,44]

deleting an obj element has BigO O(1)
That is because objects in JS behave like hashmap
deleting an array element has BigO O(n)
That is because array is special object that keeps its elements on a chunk of memory one by one without free spaces between elements. After deleting an element with i index you should move all elements that had grater than i+1 indexes to fill the released space.

Related

how to push into an index of an array without splice

splice is time complexity O(n);
I tried this version instead of splice:
which has added space complexity but i think less time complexity.
let arr = [0,1];
arr[5] = 5;
// i need to push numbers into this index only-not to the whole array
// push wont work on a 1d array but will work on 2d array
arr[5] = [[], 5];
// now it is possible to push into this index
arr[5].push(15,125,1035);
// remove the unnecessary empty cell []
arr[5].shift();
console.log(arr) // result [0,1,[5,15,125,1035]]
So is this worse than splice, or better(in terms of time complexity)?
EDIT:
this is a bad take of the answer given, my problem was i didn't understand why you couldn't push into an index of an array.
when you try:
arr = [1,2,3,4]
and then arr[1].push(2.5);
you would get an error since you try and push into a primitive(number and not an object/array).
My mistake was that i thought JS just doesn't allow it.
If you want result [5,15,125,1035] with simply this way.
let arr = [5];
arr.push(15,125,1035);
console.log(arr)
Javascript leaves the underlying implementation of arrays up to the runtime, so the answer will depend on implementation used: How are JavaScript arrays implemented?
but I will assume this array is entirely a flat array.
Pushing to the end of an flat array is only O(1) if the array has space for more elements. Otherwise the array needs to be reallocated which is O(length_of_array). However it should still be faster than splicing on every insertion.
If you want O(1) insertion speed then you could append to the end of a doubly linked list instead, however this is at the cost of space and lookup/iteration speed.
the simpler answer i was looking for is by #Gerardo Furtado
let arr = [0,1,2,3,4,5];
arr[5] = [5];
arr[5].push(15,125,1035);
console.log(arr) // result [0,1,[5,15,125,1035]]

Why 'delete' replaces value with undefined in arrays but in objects it is able to remove the property completely?

What differences in object and arrays cause this? Why is Object able to remove the element and array cannot? Does Object automatically makes a check to not display undefined values?
delete will remove properties entirely from arrays.
const array = [0,1,2];
delete array[1];
console.log("0" in array);
console.log("1" in array);
Since most tools that display an array for debugging purposes will not display them with explicit index values, any missing values will typically be rendered as undefined.
If they didn't then you wouldn't be able to tell the difference between these two examples:
const sparse = [1,,2];
const full = [1,2];
console.log(sparse);
console.log(full);
If you want to shuffle the indexes of every subsequent item down the array, then you need to look at the splice method.

Why is filter method not deleting all elements of the array?

this.arol.filter(x=>x.length!==0
?(this.arol.splice(this.arol.indexOf(x),1))
:!true)
I was trying to change it many different ways, but it still does not delete all elements of the array, it always leaves 1 or 2 behind deleting most of them.... I think the problem is with the condition... We are checking if the length of array elements is not 0 (which are all strings)...
Don't try to splice while filtering - instead, return from the filter callback a truthy or falsey value, depending on whether you want to include the item being iterated over in the new array, and use the resulting array that gets returned from .filter:
this.arol = this.arol.filter(x => x.length !== 0);
^^^^^^^^^^^^
If you want to maintain same outer array reference and mutate original you can splice in a loop if you work from end to start so as not to affect indexing you haven't arrived at yet as you change the array length:
const arr = [[1],[],[2]]
arr.reduceRight((_,c,i) => c.length || !!arr.splice(i,1))
console.log(arr)
The problem is you are trying to splice at the same time you are using filter. Filter does not remove elements from your array, it creates a new array with the filtered data, as described here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
You can assign the result to the same array as suggested by CertainPerformance.
If Splice is removed from that code then it will not delete elements. this.arol.splice(this.arol.indexOf(x),1) here it will iterate through every element inside that array and x will be current iteration which will splice from the array as you have written splice method. Remove splice it will work fine.

Can Array.splice() be used to create a sparse array by adding an element at an index beyond the last element of the array?

Can Array.splice() be used to create a sparse array by adding an element at an index beyond the last element of the array?" I need this because in some situations I just want to push onto the array, but in other situations I need to splice into the array. But trying to use splice to make the array sparse did not work, though in my particular situation I was able to implement some code to test whether to use splice, or just assign an array element at an index beyond the array's length.
No. The ECMAScript specification does not allow a relative start position greater than the array length. From ES2015 on Array.prototype.splice, step 7:
...let actualStart be min(relativeStart, len).
The variable actualStart is what's actually used for the splice algorithm. It's produced by the minimum of relativeStart (the first argument to the function) and len (the length of the array). If len is less than relativeStart, then the splice operation will use len instead the actual argument provided.
In practical terms, this means that you can only append values onto the end of arrays. You cannot use splice to position a new element past the length index.
It should be noted the length of the array is not necessarily the index of the last item in the array plus 1. It can be greater.
Then, you can't use splice to insert elements beyond the length of the array, but if you make sure the length is large enough, you can insert beyond the last index plus 1.
var arrSplice = ['what', 'ever'];
arrSplice.length = 10; // Increase the capacity
arrSplice.splice(10, 0, 'foobar'); // Now you can insert items sparsely
console.log(arrSplice.length); // 10
console.log(arrSplice[arrSplice.length - 1]); // foobar
Array.splice() cannot be used to create sparse arrays. Instead, if the index argument passed to Array.splice() is beyond the length of the array, it seems that the element just gets appended to the array as if Array.push() had been used.
/* How you might normally create a sparse array */
var arrNoSplice = ['foo', 'bar'];
arrNoSplice[10] = 'baz';
console.log(arrNoSplice.length); // 11
/* Demonstrates that you cannot use splice to create a sparse array */
var arrSplice = ['what', 'ever'];
arrSplice.splice(10, 0, 'foobar');
console.log(arrSplice.length); // 3
console.log(arrSplice[arrSplice.length - 1]); // foobar

Fast find for indices by ID

I have million of objects each have an unique ID - number.
Each object for making it simple contains name
They objects are being added into array.
Into this array i'm adding and removing objects.
In order to remove object I have the id, and then need to find the index in the array and splice it out.
In my case i have allot of objects and can have allot of removes operations. so in case i have 1000 removes. and all of this objects ids are stored in the end of the array, than i will run over the all 1 million objects till i find them.
Storing the index in the object after adding is not good, because every each remove i need to update the indices of all objects stored after the removed one.
For example removing the first 1000 will cause updating the rest of the 1M-1000 items indices.
My question is, what is the best solution for my problem?
-- UPDATE --
for example: My flat array look like this after adding 1M objects
[ obj1, obj2, obj3, .... obj1000000 ]
I want to remove now the object obj1000000. For finding which index this object
was inserted to i need to run over all the array (or till i found the item) and compare the current item id with my obj1000000 id, and break out from the loop when found. Then remove the item by it's index.
If i would store the index of each object in the object itself after it being added to the array, i would have to update the rest of the objects indices after removing one.
For example: obj1 will contains property index=0, obj2 will have index=1 and so on. To remove obj5 i just get its property index which is 4 and remove it. but now obj6 which has index=5 is incorrect. and should be 4. and obj7 should be 5 and so on. so update must be done.
My SmartArray holds an TypedArray created in some size. And i'm expending it if needed. When push is called. I'm simply set the value in the last item this._array[this.length++] = value; (Checking of course if to expand the array)
SmartArray.prototype.getArray = function () {
return this._array.subarray(0, this.length);
}
SmartArray.prototype.splice = function (index, removeCount) {
if (index + removeCount < this.length) {
var sub = this._array.subarray(index + removeCount, this.length);
this._array.set(sub, index);
} else {
removeCount = this.length - index;
}
this.length -= removeCount;
}
It is working very fast, subarray doesn't create a new array. And set is working very fast as well.
The standard solutions for this problem are
balanced (binary) trees,
hash tables.
They take respectively O(Log(N)) and O(1) operations per search/insertion/deletion on average.
Both can be implemented in an array. You will find numerous versions of them by web search.

Categories

Resources