Related
I’m trying to understand the filter method. I found a script example and modified it to multiply all elements of the original array by two:
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
console.log(list)
const multiplyByTwo = (ar) => ar.filter((word, index, arr) => {
arr[index + 1] *= 2
return true
})
console.log(multiplyByTwo(list))
}
All but the first element of the array get modified. If I change the arr[index + 1] to arr[index], none of the elements get modified. I am trying to understand how this works.
As you already know map is the correct way to achieve the mentioned requirement let me try to explain why the filter is not working.
You must understand the return value of the filter which is a new array with the elements that pass the test.
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0];
console.log("before = ", list);
const multiplyByTwo = (ar) =>
ar.filter((word, index, arr) => {
arr[index] *= 2; // <--- Manipulating the current list
return true; // <----- Return the current element: word
});
console.log("after = ", multiplyByTwo(list));
}
zeroFill();
In the case of arr[index] * 2, you are multiplying each element by 2 (and modifying the list array too) but you are returning the current element that is represented by word in the above code.
filter returns a new array with the array elements of list based on its return value.
The array values do get modified in both cases, i.e. when using arr[index + 1] *= 2 and arr[index] *= 2.
However, the value that lands in the resulting array is the same value passed as word.
See the specification:
The array element at index k of array O is retrieved and stored as kValue.
The callback function is called with arguments (kValue, k, O).
If the callback function returns a truthy value, put kValue into the resulting array.
At no point is the array element at index k of array O retrieved again.
Your modification with arr[index] *= 2 always comes too late; the value that is going to be added has already been retrieved from the array by the filter method.
Your modifications with arr[index + 1] *= 2 will modify the next index, which is the value that filter retrieves in the next iteration.
That’s why you see changed values starting from index 1.
Index 0 didn’t see a modification yet, so filter receives the original value and adds it to the resulting array.
Log list, not only multiplyByTwo(list), to see the changed values.
You are misusing filter here.
You should use map instead to change every value to a different value, or forEach if you want to mutate the array with something like arr[index + 1] *= 2.
To multiply every element by two:
console.log(list.map((value) => value * 2));
The filter function is not designed for this purpose. It's designed to filter out the array elements you need.
For your specific case, I would use .map method, as it will modify the array as needed and is designed to walk arrays.
const multiplyByTwo = (ar) => ar.map((current) => current * 2);
You are trying to modify an array with .filter which is not a good practice. You can use .map when you want to do something with the array items.
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
console.log(list)
const multiplyByTwo = ( ar) => ar.map( (item, index, ) => {
return item *= 2
})
console.log(multiplyByTwo(list))
}
zeroFill();
First I will try to explain why you got this behavior, run this code and try to understand:
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
function zeroFill() {
console.log('list before filter: ', list)
const multiplyByTwo = ( ar) => ar.filter((word, index, arr) => {
console.log(arr === list); //arr and list have the same reference
arr[index] *= 2; //you will be modifing list[index], that is the current value being filtered, so you you will get the old value
//arr[index + 1] *= 2; //you will modifying list[index + 1], so in the next loop the value will be the new one
return true
}); //The result of filter will create a new array
console.log('multiplyByTwo result:', multiplyByTwo(list))
console.log('list after filter: ', list);
}
You should use .filter just to pick the values you want based on a condition, not to modify an array while you are filtering it, you should use .map for this purpose:
const list = [1, 0, 1, 2, 3, 0, 0, 4, 0];
const multiplyByTwo = list.map((current) => current * 2);
Array.filter(), as the name states, filters the array and returns a new array containing the items that pass the filter.
What you need is Array.map() if you want a mapped (and also new) array. Otherwise you can use Array.forEach()
// In this function, a new array is created and returned, with modified items
function zeroFillWithMap() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
const multiplyByTwo = list.map(i => i*2)
console.log('Mapped New Array', multiplyByTwo)
}
zeroFillWithMap();
// In this function, a new array is NOT created and the items of the original array are modified
function zeroFillWithForEach() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
list.forEach((item, index, originalArray) => originalArray[index] *= 2)
console.log('Modified Original Array', list)
}
zeroFillWithForEach();
I am not sure if you know about the "Map Method In JS". I think the problem you proposed could be solved much easily using that method. I am gonna leave my code here on how i solved your problem.
const zeroFill = (list) => {
console.log("orignal array: " + list);
const multiplyByTwo = list.map((item) => {
return item * 2;
});
console.log("multiplied by two array: " + multiplyByTwo);
};
zeroFill([1, 0, 1, 2, 3, 0, 0, 4, 0]);
but if you need your problem solved using only the filter method, I'd be happy to help in that situation too.
And yeah, if you want to know more about "Map Method In Javascript". I am gonna link few articles from MDN and W3SCHOOL.
https://www.w3schools.com/jsref/jsref_map.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
I am trying to remove 2 elements from end using splice method
This is what I am tryed
const arr = [3,4,5,6,7];
arr.splice(-1, 2)
I am expecting arr to be [3,4,5] but arr value is [3,4,5,6]
wanted to understand why it's behaving like this
From MDN
start
The index at which to start changing the array. If greater than the
length of the array, start will be set to the length of the array. If
negative, it will begin that many elements from the end of the array.
(In this case, the origin -1, meaning -n is the index of the nth last
element, and is therefore equivalent to the index of array.length -
n.) If array.length + start is less than 0, it will begin from index
0.
index -1 means from the last element so in our case, only the last element will be deleted.
You just start by the last index of the array and remove two items.
The result is an array without 7.
// -1 index
const arr = [3, 4, 5, 6, 7];
arr.splice(-1, 2);
console.log(arr);
The easiest way to do this will be to use arr.length
const arr = [3,4,5,6,7];
arr.splice(arr.length - 2)
console.log(arr)
First param tells to splice from which index it should delete all elements
const arr = [3,4,5,6,7];
const itemsToDelete = 2;
arr.splice(arr.length - itemsToDelete, itemsToDelete)
console.log('arr', arr);
I have an array with a fixed length of 6.
I want to remove the first element from the array, then shift all the elements left by 1, but the length of the array should remain as 6 (the 6th position of the array can be undefined)
I tried using splice but the array length was reduced to 5 which is not what I want to happen.
What is the best approach to achieve the above?
You can use Array.prototype.slice (which does not mutate the original array unlike splice) to take a copy of the array from the 1st position.
Then use Array.from to get a new array from the copy and mention the length property value of the old array:
const arr = [1, 2, 3, 4, 5, 6]
const newArr = Array.from({length: arr.length, ...arr.slice(1)});
console.log(newArr);
You can shift the first element, then push undefined, as shown below:
const array = [1, 2, 3, 4, 5, 6]
array.shift()
array.push(undefined)
console.log(array)
I am not sure what I am missing. Need the new array to return the first and last element of the passed array.
var firstAndLast = function(array){
var newArray = new Array();
newArray [0] = array[0]
newArray [1] = array[3]
return plate;
}
For Example:
var array = ['one', 3, 'cool', 4];
firstAndLast(array); // returns ['one', 4]
You need to access the first and last element, and return that in an array. I'm not sure where plate comes from, but in general your function is 'correct' in the sense that you create a new array and set the first and second elements to the first and last elements of the passed array. You just need to return newArray.
But what if the the 4th element isn't the last one in the array? Then you'd have to make it more general:
var array = ['one', 3, 'cool', 4];
var firstAndLast = function(arr) {
return [arr[0], arr[arr.length - 1]]; //No need for new Array(), and you can just assign items in positions inline
}
console.log(firstAndLast(array));
The above code reduces the function into 3 lines, as it returns an array literal, with the first element as arr[0], the first element of the passed array. The second element is arr[arr.length - 1], which is the last element. Consider this:
[1, 2, 3, 4, 5]
The length currently is 5, and the last element is accessed by arr[4]. Now, just subtract one from the length to get 4, and access the last element. arr[arr.length - 1] in this case would yield 5.
var NewdateData[] = [1,2,3,4,5,6,7,8,9,1,2,1,23,45,56]
This NewdateData is dynamically filled from database depending upon the selection made from the user interface.
I am using this NewdateData for displaying under the X axis Charts.
The issue I am facing is that, the values are not taken till the end , I want to have the last value to have under the X axis Labels.
xaxis: {tickFormatter: function(n)
{
var k = Math.round(n);
return NewdateData[k];
}
I am using flotr.
You can get the last value of an array with:
NewdateData[NewdateData.length-1];
Very late to the party, but for posterity: in ES2015/ES6 you can use Array.prototype.slice. Doesn't mutate the array and a negative number gives you elements from the end of the array as a new array.
So to get the last element:
let arr = [1, 2, 3, 4, 5];
let last = arr.slice(-1); // last = 5
I don’t have enough points to comment on Radman’s post., but his solution is wrong.
let arr = [1, 2, 3, 4, 5]; let last = arr.slice(-1); // last = 5
Returns [5], not 5.
The slice() 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.
The correct answer:
let arr = [1, 2, 3, 4, 5];
let last = arr.slice(-1)[0];
References: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
Just do it with the map function.
this is the array what I want to pick the last item from it:-
const animals = ['Dodo', 'Tiger', 'Penguin', 'Dodo'];
loop over the array using map function to use the index parameter and compare it with animals array length:-
animals.map((animal, index) => animals.length -1 === index ? console.log("last item selected :)" + animal) : console.log("i'm not the last item"))
Now we are living with ES6 features
var arr = [1,2,3,4,5,6]
const [a, ...b] = arr.reverse();
console.log(a)
A simple and convenient way is to use Array.prototype.at()
function returnLast(arr) {
return arr.at(-1);
}
const cart = ['apple', 'banana', 'pear'];
const lastItem = returnLast(cart);
console.log(lastItem) //pear
or just
const lastItem = cart.at(-1)