I have a function with the objective of search for one object with same value remove it for an global array and return it but it isn't removing
function removeAndget(p){
var p2;
for(var i =0;i<waiting_list.length;i++){
if(waiting_list[i].le === p.le){
p2 =waiting_list[i];
console.log(waiting_list);
waiting_list.slice(i,1);
console.log(waiting_list);
break;
}
}
return p2;
}
I need the object removed but for some reason it remains in, someone can tell me what I am doing wrong?
You should use
array.splice(start, deleteCount)
not slice.
You're using slice() method on array with wrong format of arguments. If you want to use slice, the arguments format is different
slice(start, finish)
In your case for example slice(i, i+1)
slice() does not mutate the array, splice() does
In your example, you can use splice(i, 1)
Below are some details describing what the two functions do:
slice:
The slice(begin,end) method returns a shallow copy of a portion of an array
into a new array object selected from begin to end (end not included).
The original array will not be modified.
splice:
The splice(start,deleteCount) method changes the content of an array by removing
existing elements and/or adding new elements.
Related
selectedRoles= [1,230]
if(this.selectedRoles.length > 1)
{
this.selectedRoles= this.selectedRoles.splice(0,1);
}
I am trying to delete item at index 0 which is 1 but instead it deletes the item at index 1 which is 230.
Why ?
Because you assigned the output of splice function, which is [1] back to the original this.selectedRoles:
this.selectedRoles = this.selectedRoles.splice(0,1);
All you had to do is to remove the assignment, e.g.:
this.selectedRoles.splice(0,1);
this.selectedRoles // would be [230]
It's because you did the assignment.
this.selectedRoles = this.selectedRoles.splice(0,1);
Just need to write as below code.
this.selectedRoles.splice(0,1);
As per the documentation Array.prototype.splice is an inplace function
The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.
And, this.selectedRoles.splice(0,1) returns the deleted item which you are assigning to this.selectedRoles.
Just avoid assigning splice to the array variable.
selectedRoles= [1,230]
if(this.selectedRoles.length > 1)
{
this.selectedRoles.splice(0,1);
}
I think you have misunderstood what splice does.
The splice() method adds and/or removes array elements.
The splice()
method overwrites the original array.
Reference
this.selectedRoles.splice(0,1) would return the value at the index that is removed and not what is left inside the array, hence you are getting 1. Furthermore, you are assigning it to the same variable and thus overriding the old array with the removed values.
Return value of splice
An array containing the deleted elements.
If only one element is removed, an array of one element is returned.
If no elements are removed, an empty array is returned.
Reference
I think your requirement is to remove the first index if the length is greater than 1, in this case it is better to use slice instead of splice. slice does not alter the original array. It returns a shallow copy of elements from the original array. More information here.
I am trying to solve the following leetcode problem in JS: MoveZeroes problem
The challenge is the following:
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.
1.You must do this in-place without making a copy of the array.
2.Minimize the total number of operations.
Example:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
In my code, I get the desired output on the console right before the end of the function, but it is being rejected and I would like to understand why.
This is my code:
/**
* #param {number[]} nums
* #return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
let i = 0
let length = nums.length
while (i < length){
if(nums[i] === 0) {
nums = nums.slice(0, i).concat(nums.slice(i+1),0)
length--
continue;
}
length--
i++
}
console.log(nums) //logs the desired result
};
I have seen similar questions to this:
Using splice
This one does not do it in-place
Not doing it in-place either
So, I understand that this might be a duplicate but I would appreciate direct feedback on my code. Thanks!
your code is violating the first rule:
You must do this in-place without making a copy of the array
slice() and concat() both returns a new array which means copying the original array;
you may use shift(), unshift(), sort() ... or swap the element values, that mutate the original array
nums = nums.slice(0, i).concat(nums.slice(i+1),0)
This line assigns the nums variable to a new array with the desired content. But the original array remains unchanged.
As others have mentioned, your use of Array.slice(...) and Array.concat(...) violate the constraints of the question. Quoting some particular sections from the Mozilla Developer Network pages on each of those functions:
Array.slice(...): "The slice() method returns a shallow copy of a portion of an array into a new array object..."
Array.concat(...): "The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array. [emphasis added]"
I would highly recommend the usage of Array.splice(start[, deleteCount[, ... itemsToInsert]]) for this, which can be used not only to delete subsections of an array, but also to insert new elements into an array, all while modifying the array in-place. This versatility allows Array.splice(...) to function as an in-place replacement for both Array.concat() and Array.slice().
I would like to work with an array passed to a function while leaving the original array untouched. Here is a simple example of the problem.
function whyDoesArrChange(arr) {
var newArr = arr;
newArr.push(4);
return arr;
}
console.log(whyDoesArrChange([1,2,3]));
// OUT: [1,2,3,4]
I would like only newArr to be changed, but the arr (from the arguments) returns the pushed value as well (returns [1,2,3,4]). How can I avoid this?
When passing an array to a function, the value of that array is a reference, you have to clone it to break the reference.
There are multiple ways to achieve this:
1 - Using .slice();
var newArr = arr.slice();
2 - Using .concat
var newArr = arr.concat([]);
3 - Using JSON.parse & JSON.stringify
var newArr = JSON.parse(JSON.stringify(arr));
You can check more ways and see how they perform in this jsperf I found.
While Marcos' answer is correct, no doubt. There are more pure Array functions that can be used (A pure function is a function that doesn't alter data outside of its' scope).
Usually, if you'd like to do multiple actions on the array, I would go with Marcos' answer and then do those changes as usual. But when that's not the case, the following information may be useful:
Adding: arr.concat([1]);
Subarray (i to j): arr.slice(i, j + 1);
Removing (i to j): arr.slice(0, i).concat(arr.slice(j + 1));
Also, filter and map are pure function that will not alter the array.
In JavaScript, when you use (=) to assign a value from a variable to another one, you're just passing the entire variable, so each time one or another changes, the other will change too.
According to your question, the best way that works for me is using the native .slice() JavaScript method to the arrays object. For your code:
function whyDoesArrChange(arr) {
var newArr = arr.slice();
newArr.push(4);
return arr;
}
Because reference types (arrays and objects) can get modified inside functions when passed as arguments, while primitive types (numbers, strings, booleans etc.) don't.
You can make a shallow copy the array with .slice() and work on that array, or return a new array with the .concat method.
function whyDoesArrChange(arr) {
return arr.concat(4);
}
I am trying to create a function that mimics Array.prototype.push.
It takes a variable number of arguments and pushes them into a specific array.
I have managed to do this with the following code:
var array=[];
function append(){
for(var i=0;i<arguments.length;i++)
array.push(arguments[i]);
}
Now my question is:Can I rewrite the append function without using "for loop"?
Thanks in advance.
If you need to get arguments array, you should use Array's slice function on an arguments object, and it will convert it into a standard JavaScript array:
var array = Array.prototype.slice.call(arguments);
You could use Array.prototype.push.apply
function append(){
// make arguments an array
var args = Array.prototype.slice.call(arguments);
// return the number of elements pushed in the array
return Array.prototype.push.apply(array, args);
}
So, what's happening here with args? We use Array.prototype.slice.call with arguments, the purpose being to make arguments an array, because it is a special object. Function.prototype.call is used to call a function with a specific context (aka this), and then the arguments to call the function with (comma separated). Conveniently, it appears that slice() looks at the length property of the this context, and arguments has one too, and when not empty, has properties from 0 to length -1, which allows slice to copy arguments in a new array.
You can rewrite this without a for loop, but you have to use a loop of some sort (you're working with multiple items, it's a necessity).
If you have access to ES6 or Babel, I would use something like:
function append(...args) {
return array.concat(args);
}
Without ES6, you need to work around the fact that arguments isn't a real array. You can still apply most of the array methods to it, by accessing them through the Array prototype. Converting arguments into an array is easy enough, then you can concat the two:
function append() {
var args = Array.prototype.map.call(arguments, function (it) {
return it;
});
return array.concat(args);
}
Bear in mind that neither of these will modify the global array, but will return a new array with the combined values that can be used on its own or assigned back to array. This is somewhat easier and more robust than trying to work with push, if you're willing to array = append(...).
Actually i honestly believe that push must be redefined for the functional JS since it's returning value is the length of the resulting array and it's most of the time useless. Such as when it's needed to push a value and pass an array as a parameter to a function you cant do it inline and things get messy. Instead i would like it to return a reference to the array it's called upon or even a new array from where i can get the length information anyway. My new push proposal would be as follows;
Array.prototype.push = function(...args) {
return args.reduce(function(p,c) {
p[p.length] = c;
return p
}, this)
};
It returns a perfect reference to the array it's called upon.
I want to remove an item from an array, is array.splice(x,1) the best way to go?
Is array.splice(x,1) functionally equivalent to delete array[x]; array.length-=1 ?
I've read these threads: Javascript object with array, deleting does it actually remove the item? and Deleting array elements in JavaScript - delete vs splice
and did some tests:
<script>
var arr=[];
for(var x=0;x<100000;++x){
arr.push(x);
}
var a=new Date().getTime();
for(var x=0;x<50000;++x){
arr.splice(49999,1);
}
var b=new Date().getTime();
alert(b-a);
</script>
<script>
var arr=[];
for(var x=0;x<100000;++x){
arr.push(x);
}
var a=new Date().getTime();
for(var x=0;x<50000;++x){
delete arr[49999];
arr.length-=1;
}
var b=new Date().getTime();
alert(b-a);
</script>
The timing difference is over a magnitude of 100, making the itch to use the second solution almost irresistable.. but before using it, I would like to ask this question: are there any traps i should look out for when i use delete array[x]; array.length-=1 instead of array.splice(x,1)?
If you're just lopping off the last element in the array, you can use pop() and throw away the result or just decrement the length by 1. The delete operator isn't even required here, and splice() is more appropriate for other uses.
Specifically, section 15.4 of the ECMAScript specification says:
whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted.
Both methods mentioned are outlined at MDC:
Array pop()
Array length
Either are appropriate for your situation - by all means modify length if you get better performance from it.
array.splice may perform other internal operations relevant to the splice.
Your delete array[x]; array.length-=1 just hacks around the public interface and assumes that there's nothing else to do internally.
In fact, this is the cause of the timing difference: there is plenty more to do internally in order to actually splice the array.
Use the proper interface. That's why it's there.
Using delete does not delete the element. After delete somearr[n] somearr[n] still exists but its value is undefined. There are a few ways to remove elements from arrays.
within an array for one ore more elements: Array.splice
from the end of an array (i.e. the last element): Array.pop() or maybe Array.length = Array.length-1
from the beginning of an array (i.e. the first element): Array.shift() or Array.slice(1)
To be complete, using Array.slice you could make up a function too:
function deleteElementsFromArray(arr,pos,n){
return arr.slice(0,pos).concat(arr.slice(pos+n));
}
Deleting array elements just sets them to undefined - that's why it is so fast. It does not remove the element. Decreasing the length of the array makes it even worse as the array length doesn't change at all!
In other words: the response to your question title is no and you should use splice() to achieve the intended effect. You can use the delete 'trick' to achieve greater performance only if your code handles the possibility of undefined elements. That can be useful, but it has nothing to do with 'removing an item from an array'.