how to push into an index of an array without splice - javascript

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]]

Related

Is `Array.prototype.reduceRight` identical to `reverse` followed by `reduce`?

Array.prototype.reduceRight reduces an array to a single value, working right-to-left (i.e. starting from the end of the array).
Is calling reduceRight exactly the same as calling reverse followed by reduce? If so, why does reduceRight exist?
Array#reduceRight is not the same as Array#reverse() -> Array#reduce(). Here is the key difference .reduce()/.reduceRight() do not modify the starting array:
const arr = ["a", "b", "c"];
const combine = arr.reduceRight((a, b) => a+b, "");
console.log(combine);
console.log(arr);
However, .reverse() does:
const arr = ["a", "b", "c"];
const combine = arr.reverse().reduce((a, b) => a+b, "");
console.log(combine);
console.log(arr);
There is also question for a performance - .reverse will incur an additional O(n) processing to reverse the array in-place, that's on top of the .reduce() that already operates at O(n). Yes, the final complexity is still O(n) (we ignore the constants) but having a single pass through the array is faster.
As already mentioned, it is not the same. Here are two more use cases, where those two versions behave differently:
Everything that is based on the index (third argument of the callback function called by both reduce and reduceRight) might behave differently.
Reverse loops are often used when the original array is being modified. Depending on the exact use case, that might work with reduceRight but break with reduce.
It already was mentioned that .reverse() modifyes iinitial array,
In addition, according to spec:
https://tc39.es/ecma262/#sec-array.prototype.reduce
https://tc39.es/ecma262/#sec-array.prototype.reduceright
Implementations are a bit different.
Let me allow the analogy with .push() and .unshift() - they do also quite a same, inserting an element in array, we use push a lot, and unshift quite rarely, but time to time there are some perfect moments for unshift as well as for reduceright

How can I insert a value on every index of array using a loop and slice and/or concat?

I'm currently doing an assignment for school and could really use your help.
I have to declare a function which takes two arguments, x and an array, arr. It has to return an array which contains multiple arrays with x inserted into respectively index 0 in the first array, index 1 in the second array and so on until there's no more numbers in the array. See picture of an example and for clarification of what the final result is expected to look like. It has to work on any given array and the assignment specifies that slice() and concat() would be good to use. example of assignment
function insert_all_positions (x, arr) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
return(arr.concat(x)); }
};
This just adds the x-value to the end of the array and I have to loop it so the value will be inserted at all indexes. I'm thinking the array.splice() method can be used, I'm just not sure how as I'm not particularly experienced with it. Thank you :)
As Nina already said: the idea of assignments is, that you try something yourself which we can then help you to improve.
Nonetheless, here is one simple way of doing what was required:
function iap(v,arr){
var l=arr.length, ret=[];
for (var i=0;i<=l;i++) ret.push(arr.slice(0,i).concat([v],arr.slice(i,l)));
return ret;
}
console.log(iap(8,[1,2,3]));
Try this
function myFunc(x,arr){
let result =[]
for(let i=0;i<arr.length;i++){
let arrToAdd = [...arr]
arrToAdd[i]=x
result.push(arrToAdd)
}
return result
}
You create a result array that you push your arrays into, then you run a loop that will run the exact number of times as the length of your argument arr. Each iteration of the loop creates a new array that is a copy of arr and then you just change one number in it each time and add the entire array to the result.

Deleting Array Element in js?

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.

Why array.forEach(() => { array.pop() }) would not empty the array

While on the nodejs REPL I was trying to clean up an array defined as const array = [...] and just found out that using array.forEach(() => /pop|shift/()) would not work. After such expression the array will still hold values in it.
I'm well aware of better methods to clean the array, like array.splice(0), but I'm really curious about this behavior as seems counter-intuitive, at least for me.
Here's the test:
const a = [1, 2, 3]
a.forEach(() => {
a.shift()
})
console.log(a) // [ 3 ]
const b = [1, 2, 3]
b.forEach(() => {
b.pop()
})
console.log(b) // prints [ 1 ]
Notes
At first I was using arr.forEach(() => arr.pop()), so I though that one of the values was short-circuiting the forEach but wrapping the lambda in a body-block { .. } will also produce the same results.
The results are consistent across different node versions and browsers .. so it seems like it's well-defined behavior.
The quantity of leftover values, those still in the result array, change depending on the length of the input array, and seems to be Math.floor(array.length / 2)
The leftover values are always ordered accordingly to the /pop|shift/ method used, so some of the calls are actually changing the input array.
It also returns the same results by calling Array.prototype.forEach(array, fn)
Check out this quote from here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
If the values of existing elements of the array are changed, the
value passed to callback will be the value at the time forEach()
visits them; elements that are deleted before being visited are not
visited.
You're iterating from the beginning and removing the last element each iteration. This means you're moving forward 1, and reducing the length by 1, each iteration. Hence why you're ending up with floor(initialLength / 2) iterations. You're modifying the same array that you're forEaching, which as stated above means that you will not have the callback invoked for those pop'd elements.
Modifying an array while iterating over it is generally a bad idea. In fact, in Java, trying to do so would cause an exception to be thrown. But let's convert the forEach into an old-school for loop, and maybe you'll see the issue.
for (let i = 0; i < a.length; ++i) {
a.pop();
}
Is it clearer now what's going on? Each iteration you're shortening the length of the array by 1 when you pop the last element off. So the loop will end after iterating over half the elements -- because by then, it will have REMOVED half the elements, too, causing the value of i to be more than the current length of the array.
The same thing is happening when you use forEach: you're shortening the array with each iteration when you pop, causing the loop to terminate after only half the elements have been iterated. In other words, the iterator variable will move forward past the end of the array as the array shrinks.
.pop
Let's do this instead:
let arr = 'abcde'.split('');
arr.forEach((x,i,a) => {
console.log('before', x,i,a);
arr.pop();
console.log('after', x,i,a);
});
console.log(arr);
Your index is incrementing but your length is decrementing, so you're deleting the last elements when your index is in the first elements, thus the result where you delete the right half of the array.
.shift
Same: the iterating index goes one way, the length in another, so the whole things stop mid-work:
let arr = 'abcde'.split('');
arr.forEach((x,i,a) => {
console.log('before', x,i,a);
arr.shift();
console.log('after', x,i,a);
});
console.log(arr);

Time complexity of removing elements

I have a sorted Array:
let mySortedArray = [1,1,5,6,8,8,9,25,25]
I want to remove any duplicates from this array in O(1) time and space complexity. First of all, is this even possible?
My solution is the following:
I convert the array to a set and any duplicates are just removed.
let mySet = new Set(myArray);
What would the time and space complexity of that be?
And if I were to convert the set back to an Array:
let myNewArr = Array.from(mySet);
What would the time and space complexity of the whole method then be?
Would this be the most optimal way of removing any duplicates of an array or would there be a better one?

Categories

Resources