I know code below is worst.However, I want to know why?
const hello = (list) => {
list = list.map((item, index) => {
if (index === 3) {
list.splice(index, 1)
}
return item
})
console.log(list)
}
hello([1, 2, 3, 4])
why the result is [1,2,3,4],not [1,2,3]?
thanks very much!
If you see the polyfill section in the Array.prototype.map docs on how the map is implemented, you would see that the array on which the map is called is copied initially into a variable.
A loop is then used to iterate through the elements of the copied array till it reaches the length of the array. In each iteration the callback function which you supply is called to transform each element of the array and put inside a new array which is then returned from the map function.
So even though you mutate the array after you call the map it will still refer the original data and not the new one.
If you want to skip over certain elements you should use filter instead of map.
const hello = (list) => {
list = list.filter((item, index) => {
return index !== 3;
})
console.log(list)
}
hello([1, 2, 3, 4])
.map creates a new array, created from the return value of each iteration over the old array. Your
return item
inside the .map means that the new array created will be exactly the same as the original array (a shallow copy).
Each element of an array will be called with .map's callback even if the array gets changed in the meantime - the fact that the original list array has gotten spliced doesn't have any visible effect, because the .map already has a reference to every item that was in the array at the beginning, when .map was called.
If you had spliced item 3 before mapping, the result would indeed be [1, 2, 3]:
const hello = (list) => {
list.splice(3, 1);
list = list.map((item, index) => {
return item
})
console.log(list)
}
hello([1, 2, 3, 4])
Related
I'm working with a React useState variable. I have an array of objects that has 18 objects at this top level. I'm trying to update the object at the 14th index and then return the remaining objects after it. At first I was directly mutating the state by pushing my changes to it like so:
setFormWizard(wizard => {
wizard.controls[14].trash = true;
return ({
...wizard,
wizard: wizard.controls[14].group.push(...newSection.slice(0, 5)),
});
});
This works, but I'm told this isn't good practice because React may not catch the update if you push directly to the state in certain cases. So now I'm trying to use the spread operator instead.
What's happening is the first 14 objects are returning. The object I'm modifying is returning, but the rest of the objects that come after the 14th index are not returning. What am I doing wrong?
setFormWizard(wizard => {
const subjectControls = wizard.controls[14]
const groups = [...controls.group, ...subjectAddressCopy.slice(0, 5)]
return ({
...wizard,
controls: [
...wizard.controls.splice(0,14), // keep first 14 entries
{
...subjectControls,
group: groups,
trash: true
} // modify the 15th entry
...wizard.controls.splice(15) // this doesn't return the remaining controls
],
});
});
bcz splice changes in actual array you need to use slice
const arr = [1, 2, 3, 4]
arr.splice(0,2)
console.log('splice change in array so actual value of arr is :', arr)
const arr1 = [1,2,3,4,5]
// it will take slice(start, end) but end not included in return value
const cutSection = arr1.slice(1, 3);
console.log('portion of array', cutSection)
You might've wanted to use slice to return everything upwards from index 15.
Suppose I have an array var arr = [1,2,3] and if I do var result = arr.filter(callback) I want value of result would be [2,4,6] by the use of filter. I want to only define callback function in order to do so. It can be easily done with map but I want to use only filter.
Array.prototype.filter only filters existing values in an array, effectively creating a new array that can hold the same values, their subset, or an empty array, based on the filtering function.
You could do it using filter():
const arr = [1, 2, 3];
arr.filter((c, i) => {
arr[i] = +arr[i] * 2;
return true;
});
console.log(arr)
we are always returning true, so filter() makes no sense in this case.
As stated many times, there is no reason why you should do it.
It is impossible to do it like map because map returns a new array. You can either alter on the original array or you have to make a clone of the original array so you do not change it.
// this modifies the orginal array
var arr1 = [1,2,3]
arr1.filter((v,index,arr)=>{
arr[index] = v * 2;
return true
})
console.log(arr1)
// or you can clone it and do the same thing
// this modifies the cloned array
var arr2 = [1,2,3]
var arr3 = arr2.slice()
arr3.filter((v,index,arr)=>{
arr[index] = v * 2;
return true
})
console.log(arr2, arr3)
So no, you can not recreate map with filter since you HAVE to modify the original array or cheat and use a copy of the array.
So I'm not sure I understand the second part of your question, but as for the first part:
The callback for filter has three arguments, two of which are optional.
The first argument is the current element in the traversal, and the second and third arguments (the optional ones) are the 0-based index of the current element, and a reference to the original array.
This third parameter is useful for what you're trying to do.
let myArr = [1, 2, 3];
myArr.filter((el, ind, orig) => {
orig[ind] = orig[ind] + 1; // Or, whatever map logic you want to use
return true; // since a Boolean condition must be returned here
});
This way you can do it without even even having to break the scope of the function!
If you want to do it without necessarily having a variable to originally call filter on (you do have to pass an array), you can use the prototype and the call method:
Array.prototype.filter.call([1, 2, 3], (el, ind, orig) => {
orig[ind] = orig[ind] + 1;
return true;
});
function reverse(array,item){
let word = Math.ceil(array.length/2)
return array.splice(word,0,item)
}
console.log(reverse([1,2,4,5,6],3))
I was wondering why I'm getting a an empty array when the I call the function, instead of [1,2,3,4,5,6]?
Array#splice returns the items of the second parameter's count, the items who are deleted.
For returning the array, you need to return then array and not the spliced items.
function reverse(array, item) {
let word = Math.ceil(array.length / 2);
array.splice(word, 0, item);
return array;
}
console.log(reverse([1, 2, 4, 5, 6], 3));
splice does not return a new array, it modifies the input array. you need to return explicitly
function reverse(array,item){
let word = Math.ceil(array.length/2)
array.splice(word,0,item)
return array
}
console.log(reverse([1,2,4,5,6],3))
array.splice(...) does not return a new array, it modifies the input array. Per MDN, its return value is:
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.
If your intention is to create a function that inserts without modifying the original array, here's a good example: https://stackoverflow.com/a/38181008/1266600.
splice() changes the original array whereas slice() doesn't.
If you don't want to alter the original array, use slice.
function reverse(array,item){
let word = Math.ceil(array.length/2)
return [].concat(array.slice(0,word - 1), item, array.slice(word - 1));
}
console.log(reverse([1,2,4,5,6],3))
Let's say we have an array a = [1,2,3,4,5] and I want to zero it [0,0,0,0,0] by using function.
This works:
function clear (arr) {
arr.forEach((element, index) => {arr[index] = 0});
}
But this don't:
function clear2 (arr) {
arr = [...arr].fill(0);
}
Just arr.fill(0) inside clear2() works, but it's running inside Vue.js so I can't assign array elements by index, I need to reassign array var completely to remain reactivity.
Why clear2() doesn't work? Arrays as a case of Objects should be passed by reference, so what am I doing wrong?
Update: I use it as a on-click method in Vue so I can't return from it and want to pass different arrays as a parameter.
With
arr = [...arr].fill(0);
you're creating a copy of the original array then chaning that copy's values and then setting the parameter's reference value to the new array (you're not updating the parameter's inner state)
with
arr.forEach((element, index) => {arr[index] = 0});
you're actually updating the array parameter inner state
You could use fill directly, because
The fill method is a mutable method, it will change this object itself, and return it, not just return a copy of it.
function clear(array) {
array.fill(0);
}
var array = [1, 2, 3, 4];
clear(array);
console.log(array);
I am having problems understanding the concept of Array.map. I did go to Mozilla and Tutorials Point, but they provided very limited info regarding this.
This is how I am using Array.map. It is a little complex (a bit of d3.js involved; just ignore it)
var mapCell = function (row) {
return columns.map(function(column) {
return { column : column, value : getColumnCell(row, column) }
})
}
//getColumnCell is a function defined in my code
//columns is array defined at the top of my code
I do not understand exactly what this code is doing. I know its returning a new array and stuff but this part is a little tricky!
If you want to go through my code: http://jsfiddle.net/ddfsb/2/
I am using console to actually understand what's happening inside the code. Looking at the answers provided, I have clearly understood the concept of array.map. Now the only part remaining is parameters rows and columns, but there is a difference between row and rows, and column and columns in the fiddle provided
var rows//completely ok
var columns//completely ok
funcion(row)//here,source of row is unknown.getColumncell function utilizes this parameter further making it more critical
function(column)//source of column is unknown..getColumncell function utilizes this parameter further making it more critical
Let's rewrite it a bit, and start working from inside out.
var mapCell = function (row) {
return columns.map(
function(column) {
return {
column : column,
value : getColumnCell(row, column)
}
}
)
}
The function(column) part is essentially a function that takes a column as a parameter, and returns a new object with two properties:
column, that is the original value of the parameter, and
value, that is the result of calling the getColumnCell function on the row (external variable) and column (parameter)
The columns.map() part calls the Array.map function, that takes an array and a function, and runs the function for every last item of it, and returns the results. i.e. if the input is the array [1, 2, 3, 4, 5] and the function is something like isEven, the result will be the array [false, true, false, true, false]. In your case, the input are the columns, and the output is a list of objects, each of which has a column and a value properties.
Lastly, the var mapCell = function (row) part declares that the variable mapCell will contain a function of one variable called row - and this is the same row that is used in the inner function.
In a single sentence, this line of code, declares a function that when run, will take a row and return values for all columns for that row.
map loops through your original array and calls the method for each value in the array. It collects the results of your function to create a new array with the results. You are "mapping" the array of values into a new array of mapped values. Your code is equivalent to:
var mapCell = function (row) {
var result = [];
for (var i = 0; i < columns.length; ++i) {
var mappedValue = {
column: columns[i],
value : getColumnCell(row, columns[i])
};
result.push(mappedValue);
}
return result;
};
Understanding the map function is only part of the solution here, there is also the function mapCell. It takes one parameter row and it returns something like:
[ {
"column": "parties",
"value": [cell value]
}, {
"column": "star-speak",
"value": [cell value]
} ]
Where the cell value depends on the row and the column (parties, stars-speak etc.)
A map function applies a transformation to a value, and returns that transformed value.
A simple example:
function square(x) { return x * x; }
[ 2, 3, 4 ].map(square); // gives: [ 4, 9, 16 ]
Similarly:
[ "parties", "starspeak" ].map(function (column) {
return {
column: column,
value: findTheValue(column)
}
});
Now since that map is nested with a function that gets a row parameter. You can use it in the map function, to get:
function (row) {
return [ "parties", "starspeak" ].map(function (column) {
return {
column: column,
value: findTheValue(row, column)
}
});
}
And this gets pretty close to your code.
Map function goes through each element of an array in ascending order and invokes function f on all of them.
It returns new array which is being computed after function is invoked on it.
Syntax:
array.map(f)
Example:
<!doctype html>
<html>
<head>
<script>
var arr = [4,5,6];
document.write(arr.map(function(x){return x*2;}));
</script>
</head>
</html>
Answer: 8,10,12
Summary
Array.map is a function which is located on Array.prototype.map. The function does the following:
Creates a new array with the same amount of entries/elements.
Executes a callback function, this function receives and current array element as an argument and returns the entry for the new array.
Returns the newly created array.
Example:
Basic usage:
const array = [1, 2, 3, 4];
// receive each element of array then multiply it times two
// map returns a new array
const map = array.map(x => x * 2);
console.log(map);
The callback function also exposes an index and the original array:
const array = [1, 2, 3, 4];
// the callback function can also receive the index and the
// original array on which map was called upon
const map = array.map((x, index, array) => {
console.log(index);
console.log(array);
return x + index;
});
console.log(map);
Probably most people coming here (like me) just want a basic array.map usage example:
myArray = [1,2,3]
mappedArray = [];
mappedArray = myArray.map(function(currentValue){
return currentValue *= 2;
})
//myArray is still [1,2,3]
//mappedArray is now [2,4,6]
This is it at it's most basic. For additional parameers, check out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
IF you have an array of elements and you have to perform the same operation on the
each element of the array that time you can use the javascript map function for array
it helps to iterate throw the array then we can perform the operation of each element and
return it.
let NumberArray = [1,2,3,4,5,6,7,8];
let UpdatedArray = NumberArray.map( (Num , index )=>{
return Num*10;
})
console.log(UpdatedArray);
//UpdatedArray ==> [10, 20, 30, 40, 50, 60, 70, 80]
Javascript map() Syntax
arrayObj.map(callback[,context]);
arrayObj is a original array on which map() is invoked.
The map() takes 2 named arguments, First is a callback function and the second is a context object. callback function gets triggered on every element of an array.
In addition, callback function takes 3 arguments:
function callback(currentElement,index,array){
}
currentElement – This is a current elements of array which is passed to callback function
index – Index of the current element
array – complete array on which map() is applied
Out of these 3 elements, currentElement parameter is mandatory while the rest 2 parameters are optional.
However, map() does not change the original array, it creates a new array element which is generated by callback function.
You can read more on JavaScript map function
Array map() method returns a new array.
It does not change the original array.
let array = arr.map((c, i, arr) => { //return element to new array });
here,
array is the new array that is returned.
arr is the original array on which the map method is called.
c is the current value that is being processed.
i is the index of current value.
For example:-
const originalArr = [4, 3, 2]; let newArr = originalArr.map((val) => val + val);
result:-
newArr: [8, 6, 4]
originalArr: [4, 3, 2]
in simple words you can perform operations on array using map
Examples
1.Array
let arr = ["sam","tom"]
console.log("Before map :",arr)
arr.map((d,i)=>{
arr[i] = d+"yy"
})
console.log("After map :",arr)
Examples
2.Array Of Objects
// console.log(Date.now());
let arr = [
{name:"sam",roll_no:10},
{name:"tom",roll_no:12}
]
console.log("Before map :",arr)
arr.map(d=>{
if(d.name == "sam")
{
d.name = "sammy",
d.roll_no=100
}
})
console.log("After map :",arr)