Why does splice remove one number ahead of it in javascript? - javascript

Kinda wierd but i have an array
var array = [ 1, 2, 3, 4];
and if i do array.splice(1);
it removes the 2 , 3 and the 4?
how do I remove only the 2 and leave both 3 and 4 as is?
so it would be var array = [ 1, 3, 4]; ?

You have to tell splice how many elements to remove:
array.splice(1,1); # start at index 1, remove 1
I am not sure if the form you used without that parameter is a standard, actually. It could be a browser-specific (Firefox/Spidermonkey) extension.
You can add even more parameters. Those will be elements to replace the removed elements with.
It's a versatile function, take a look at the documentation.

Function splice takes two or more arguments.
The first argument means the index of the first item to be removed.
The second argumemt means the number of items to be removed.
The third and after are data to replace removed items.
Your code lacks the second argument, so splice function removed all items after the index which is specified by first argument.
array.splice(1,1);
will remove only one item at index 1, so [1,2,3,4] becomes [1,3,4].

Related

why does javascript parse an array as a string when passed in as an argument or as an index

consider this code
example 1:
function plus(a) {return a+10}
([1]) // "110"
example 2:
var arr = [1,2,3,4,5,6,7]
arr[[1]] // 2
arr.splice([1],1);
arr // (6) [1, 3, 4, 5, 6, 7]
can someone explain why passing in an array as an argument, gets converted to a string? (that's what it looks like happened here)
can someone explain why passing in an array as an argument
It doesn't.
It gets treated as an array right up until the point where you try to use the addition operator on it.
It hits the step Let rprim be ? ToPrimitive(rval) and converts it according to those rules.
And so on until it calls the array's toString method.
Similar rules apply in the other examples.
In short: When it makes no sense at all to use an array in a given context, type conversion is applied to turn it into a data type that is apropriate.
Javascript automatically outputs a certain data type when two different data types are added.
Here are two examples:
2 + 3 // 5
2 + "hello" // "2hello"
When two numbers are added, an integer is output. However, 2 and hello can't be added numerically, so everything is first automatically converted to a string, and then appended.
The same thing happens in your case – a remains an array, but an array can't be added to a number. So both are converted to strings and then appended, and the end result is a string.
You were probablly thinking of adding a value to the end of an array. This is done using:
a.push(10);
Or, if you wanted to add the first item in the array and 10 to get the result 11, use:
return a[0] + 10
But you can't add a single number to a whole array, only to one of the items or at the end of the array.
Answer #1 - you get a string from the array.toString so you need to cast back to number - here I use +
function plus(a) {return +a+10}
console.log(plus([1]))
Second
var arr = [1,2,3,4,5,6,7]
console.log(arr[1]) // 2
console.log(arr[[1]]) // 2
arr.splice([1],1); // removes the second item
console.log(arr)
var arr = [1,2,3,4,5,6,7]
arr.splice(1,1); // just as if you had done this
console.log(arr) // [1, 3, 4, 5, 6, 7]
The + operator doesn't work for arrays. It only works for numbers or strings.
Since javascript can't use your array with the + operator, it converts it to string before. That's why plus([1]) is "110"
You can use the push method if you want to add to an array:
array.push(newElement);
In the second example, inside splice, your array is used with an operator that doesn't support it so it is converted to a number. If you look at the MDN definition of splice, you see it expects a number, not an array.
When you want to use splice, you don't pass an array as the first argument, you pass the index of the first element to remove. If you want to remove 2 from your array, you do arr.splice(1,1);

Concept about flatten use recursion with reduce and concat

Now I would like to flattening the array with multiple layers
From the other solution before and the developer's network, There is an effective solution:
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
flattenDeep(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
However, there is a couple questions about the theory at that back that I want to ask:
1. In my understanding, the function starts with initial value acc, and then it keeps looping all the element to see if it is an array or not.
In this case, the first 3 elements are 1,2,3 -- therefore is not an array and will be accumulated and returned as an array.
But start from the fourth element it returns
Array.isArray(arr1[3])
(5) [1, 2, 3, 4, Array(3)]
In this case, it triggers the condition acc.concat(flattenDeep(val)), which is a recursion of the function. How this condition helps to flatten the array?
And for the [] at the back, if my understand is right, it indicates the return form of the result from reduce should be an array?
Last but not least, any good reference for this topics that I should look for?
May thanks for your help!
Further elaboration:
let's say, now the val in the reduce function above is [1, 2, 3, 4,[[2,3,4]]].
In this first round of checking, the elements 1,2,3,4 are not array, but the last element still does, and it makes the whole argument still an array. For the next round of the recursion, would it just take the element [[2,3,4]]] and further evaluate the elements inside this array?
Or with this example, what would be the first, second and third round outcome of the recursion process?
Second argument in the reduce method is the starting condition. If there is nothing provided, first acc will be the first array's element (see array.prototype.reduce on mdn).
I'm not sure about the But there is nth to indicate the reduction of the array statement. You're calling function recursively until you will find something that's not an array and then you're returning that value.
Look for js call stack, understand how js is stacking the functions, you can even draw it, it will help definitely because it's not easy case :)

Do undefined elements in an array have an impact in JS? [duplicate]

This question already has answers here:
Deleting array elements in JavaScript - delete vs splice
(29 answers)
Closed 4 years ago.
I couldn't find a question that specifically targets the issue I'm having hence this question is being asked.
I have an array that holds 5 numbers:
var numbers = [0,1,2,3,4];
Once a number is clicked on the frontend (website), the number is removed from the array using the below code:
delete numbers[1];
This removes the correct number but leaves a space where the number was (the space is undefined). I believe this is causing an issue. After a number is removed from the array, I use another function to randomly pick any of the remaining numbers in the array however it sometimes fails. After much thought, I've realized it may be because there are empty spaces in the array after a number is removed and as a result, the code fails to work due to the undefined element.
Is my analogy correct or am I mistaken?
(I have also attempted to use the splice method to remove the number however that then causes an issue with the length of my array because if I later want to remove another number, it removes the wrong one due to the numbers moving around etc).
What you'd want to use is splice
In your specific case, numbers.splice(1,1)
You're correct that delete replaces one of the values in the array with undefined, and does not change the array length. Later on when you randomly choose an element from the array, you can wind up getting that undefined value, because it's still taking up a slot in the array:
var numbers = [0,1,2,3,4];
delete numbers[3];
console.log(numbers)
Instead use splice, which removes the item from the array completely:
var numbers = [0,1,2,3,4];
numbers.splice(3,1) /// remove one element starting at index 3
console.log(numbers)
if I later want to remove another number, it removes the wrong one due to the numbers moving around
You do need to choose one behavior or the other. If you need to preserve indexes as is, then continue to use delete, leaving the undefined values in the array, and rewrite your "choose one at random" function to never pick undefined values:
// start with some undefined values:
var numbers = [0, 1, undefined, undefined, undefined, 5]
var pickRandom = function(numbers) {
// make a copy of the array, removing undefined elements:
var definedValues = numbers.filter(function(item) {
return item !== undefined;
});
if (definedValues.length === 0) {return false}
//choose one at random:
return definedValues[Math.floor(Math.random() * definedValues.length)]
}
// test it:
console.log(pickRandom(numbers));
console.log(pickRandom(numbers));
console.log(pickRandom(numbers));
console.log(pickRandom(numbers));
(...but note that this suggests that a simple array is the wrong data structure to use here; you may be better off with an array of objects each with an explicit ID, so you can reference specific ones as needed without worrying about keeping the array index the same.)
If you mean to actually remove the element from the array, leaving your array with 4 elements, then you can use
numbers.splice(1);
This will remove the element in the index 1 from the array and return the section of the new array.

Vue: How to remove object from array by it's value?

Is it's possible to remove object from array by it's value, not by index without iteration with for loop?
I tried to remove element with iteration, but it's look like that it do not remove iteration elements:
App.$refs.userContent.foo : [1,2,3,4]
console.log(App.$refs.userContent.foo);
App.$refs.userContent.foo.forEach(function(x,i)
{
App.$refs.userContent.foo.$remove(i);
});
console.log(App.$refs.userContent.foo);
Result:
[1, 2, 3, 4, __ob__: Observer]
[3, 4, __ob__: Observer]
Why it's do not remove all elements?
As you're removing elements from the array, you're changing the index of the ones that remain. If you wanted to remove all the elements, you'd do the following inside your .forEach() :
// Keep removing first array element until they're all gone
App.$refs.userContent.foo.$remove(0);
...but that would be strange to empty an array.
To answer your original question - No. You cannot remove an array element by its value in one step. You first have to find the index of the element, and then remove it by index. In vanilla JS, you can use .splice() to remove an element by its index:
// Remove 4th element from array
myArray.splice(3, 1);
You may want to use the filter function. For example:
[1,2,3,4].filter(x => x != 2)
to remove item from the array whose value is 2.
It has to iterate the array to find the element you want removed by value. So the answer is no.
You may be able to trick it into deceiving you about how it is doing this, but ultimately it will still have to find the element with the value you want removed. There are methods to optimize the search though if the array is sorted.
In Vue 1 there's a $remove method on arrays where that you can pass a reference to.
this.items.$remove(item)
I think that's gone in Vue 2 though. You can use indexOf instead of looping through. Something like:
var index = this.items.indexOf(item);
if (index > -1) {
this.items.splice(index, 1)
}
I had the same problem, i fix it putting :key in the v-for

Angularjs comparing elements from two arrays

I have one array something like following:
$scope.blinkedBoxes=[3,4,1,2,..]
It will have upto 8 elements in total (elements will be one of the numbers from 1,2,3,4).
Another array is like following:
$scope.clickedImages=[2,4,3,1,...]
I am building following function:
$scope.checkCrossCorrectness = function(array1, array2){}
My requirement is:
If the first element of $scope.blinkingBoxes is 2 (or basically any from 1, 2, 3, 4) then in $scope.clickedImages first element can not be 2 (or same as first element of first array), instead could be 1, 3, or 4.
This logic continues for further elements as well (i.e. in first array at second position if 3 comes then in second array second position can be occupied by either 1, 2 or 4)
How can I implement this?
I dont really know if this has anything to do with angular specifically, but from what I can tell a simple forEach loop will do to check equality between the indexes.
Example:
$scope.blinkedBoxes = [1, 2 ..] // etc
$scope.clickedImages = [2, 1, ..] // etc
function functionToRunOnClickOrWhatever(){
$scope.blinkedBoxes.forEach(function(val, index){
var isEqual = val === $scope.clickedImages[index];
if(isEqual){
// do something?
}
});
}

Categories

Resources