I have a function that takes in an array of objects and a string, which represents a property. The function should return an array containing that property from each object.
Here is my sample code:
function pluck(array, property) {
var newArr = [];
array.map(function(paints){
return newArr.push(paints[property]);
});
return newArr;
}
This returns a new array and it works. But when the function is taking in an array of objects as one of the arguments...what gets passed to the anonymous iterator function in the map method? The value of the key?
How would it iterate over an array of objects using the map method?
The comments on your question explain what is happening in your code.
When you call map on an array, the mapping function is provided with 3 arguments, which are used always, sometimes and rarely in that order.
const result = items.map(function(element, index, items) {
// do the mapping
});
The function is called for each element of the original array items in turn, and the result of the function placed in the same index position of the result array.
The function arguments are:
element - this is the current element from the array
index - the current index
items - the original array on which map was called
Your pluck function could be written as:
function pluck(arr, prop) {
return arr.map(item => item[prop]);
}
Related
I am trying to create an object with modified keys after map() function (the data is from API), here is my code:
const getData = mySchedule.schedules.map((data) => ({
[data.id]: false,
}));
setCheckId(getData);
This code return:
And I want this output:
Do you have any solution for this case? thank you.
Solution:
Create an object => const getData = {};
Iterate => mySchedule.schedules
Set id as a key and false as value => getData[item.id] = false;
const getData = {};
mySchedule.schedules.forEach(item => {
getData[item.id] = false;
});
setCheckId(getData);
The above answer is correct, but let's dive deep into the problem first:
The map function returns an Array, what you want is an Object. The map function applies the callback for every element and returns a new array of elements modified by the callback function. What are you seeing is the array returned by the map function, note that 1,2,3,4is the index position of the array. Read more about the function map here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
The output that you want is an object, but as we have learned before the map function always returns an array with new elements resulting from your map function callback.
If you want an object that are many ways to achieve that, you can loop through the array and add properties to the object.
If you want to understand more and dive into array methods, you can even achieve that using reduce method, therefore the first answer is simpler:
/* Another example using reducer */
const data = [ {10:false,20:false}];
const reducer = (accumulator, currentValue) => currentValue[accumulator] = false;
setCheckId(data.reduce(reducer));
I don't understand why the followings provide different results, and on the second one I see people using an underscore (_, i), but I am not really sure what it does.
let test1 = Array.from(5, (v,i) => i); //empty array;
let test2 = Array.from({length:5}, (v,i) => i); // [0,1,2,3,4]
I don't get why I need to pass an object to get an array populated of the first n numbers.
Could someone please explain?
Let's see the signature of Array.from() method first.
Array.from(arrayLike, mapFn)
So, the first argument should be an arrayLike object (an object that has a length property of a non-negative integer). You can pass an array, string, etc. as well.
The second parameter is a map function which maps the the elements of the first argument (arrayLike) to the returned value from the callback function.
This map function takes a callback function with following signature.
callback(value, index)
The map function creates a new array populated with the results of calling the callback function (v, i) => i on every element in first argument of Array.from.
Now, let's see first case,
let test1 = Array.from(5, (v,i) => i);
Here, (v, i) => i is a map function. v is element of arrayLike object and i is the index of that element. The index i is returned.
But, 5 is neither an array nor an arrayLike object and the length property of 5 is undefined. So, map function maps no (zero) element and produces an empty array. Think of the following implementation.
function mapFn (arrayLike, callback) {
let result = [];
for (let i = 0; i < arrayLike.length; i++) {
let mappedValue = callback(arrayLike[i], i);
result.push(mappedValue);
}
return result;
}
If you pass 5 to the mapFn function, the for loop iterates 0 times and mapFn returns an empty array.
In case of second example,
let test2 = Array.from({length:5}, (v,i) => i); // [0,1,2,3,4]
{length: 5} is an arrayLike object. The map function produces an array with returned values of the callback function. The callback function returns index. Hence, [0,1,2,3,4].
In the callback function only the i parameter is used and returned from the function. v argument is not used. But, it needs to be there so that the second parameter i can be accessed. So, (_, i) is same as (v, i). You can name the parameters with any valid variable name.
You are basically following the following approach
Array.from(arrayLike, (currentValue, index) => { ... } )
So the arrayLike variable needs to be either a string, map ... or it should be an object determining the length of the array (like in your case). So in your case the size of the array is determined by the arrayLike object. currentvalue is undefined every time the arrow function runs and the index goes from 0 to arrayLike.length - 1.
Because it is expecting and arrayLike object and arrays have a length property.
I don't know why this is happening but in an array where i am running the map function, the callback function of maps get its first argument as the index number instead of the item. If I assign two arguments then it's working like how it should work i.e first arg as index and second arg as item but when i assign only one argument it gives me index number instead of the item itself.
Below is my function block:
return companies_det.map(function (company_det) {
console.log(company_det);
var $ = cheerio.load(company_det);
var company_name = $(company_det).find('a').text(),
company_esomar_url = $(company_det).find('a').attr('href');
return Rq(company_esomar_url)
.then(function (web_data) {
var $ = cheerio.load(web_data);
return {
company_name: company_name,
company_url: $('a[data-ga-category="website"]').attr('href')
}
})
.catch(function (err) {
return err;
})
});
In the above function, If I do console.log(company_det) I receive index number instead of the companies_det array items.
That is not possible if companies_det is an Array of objects and map is Array.map.
You have not provided the code with the actual problem. Either you stored the array indices in companies_det, or companies_det is not an array and it is not the standard map function.
Try logging companies_det.
A general question on JavaScript. If I have a function which modifies an array, such as:
var some_array = [];
function a_function(input, array){
//do stuff to array
return array;
}
In most languages:
var some_array = [];
some_array = a_function(input, some_array);
console.log(some_array);
works, however in js the below works as well:
var some_array = [];
a_function(input, some_array);
console.log(some_array);
Is this correct and how is this working?
Arrays in JS are objects and are passed into functions by value, where that value is a reference to the array. In other words, an array passed as an argument to a function still points to the same memory as the outer array.
This means that changing the array contents within the function changes the array passed from outside the function.
function f(arr) {
arr.push(1);
return arr;
}
var array = [];
// both function calls bellow add an element to the same array and then return a reference to that array.
// adds an element to the array and returns it.
// It overrides the previous reference to the array with a
// new reference to the same array.
array = f(array);
console.log(array); // [1]
// adds an element to the array and ignores the returned reference.
f(array);
console.log(array); // [1, 1]
As others have mentioned this code comes from chapter 6 of eloquent javascript. I do not understand where the arguments to the function 'drawRow' are supplied from. If the outer function drawTable were some sort of method it would make sense that it could pass an array as well as the current index, but it's not. It's just an ordinary function so where does it grab 'row' and 'rowNum' from?
function drawTable(rows) {
var heights = rowHeights(rows);
var widths = colWidths(rows);
function drawLine(blocks, lineNo) {
return blocks.map(function(block) {
return block[lineNo];
}).join(" ");
}
function drawRow(row, rowNum) {
var blocks = row.map(function(cell, colNum) {
return cell.draw(widths[colNum], heights[rowNum]);
});
return blocks[0].map(function(_, lineNo) {
return drawLine(blocks, lineNo);
}).join("\n");
}
return rows.map(drawRow).join("\n");
}
Thank you in advance to anyone taking the time to answer this.
According to MDN Array.prototype.map, the callback supplied to map has three parameters: currentValue, index, and array. In this case, when drawRow is supplied to rows.map, row is the currentValue, and rowNum is the index.
Here's a simpler example:
var arr = ['a', 'b', 'c'];
function printArray(value, index) {
console.log(index + ' ' + value);
}
arr.map(printArray);
// prints
// 0 a
// 1 b
// 2 c
The map function calls the provided callback (drawRow in your case) with three arguments for each element of the array that it is iterating over:
the element
the index
the whole array (which you are not making use of here)
You could optionally also set some object to become this inside of the callback.
As others have mentioned, the map method calls drawRow passing the appropriate values. To illustrate the mechanics behind this let's create another function, called M_A_P, from scratch that would also call drawRow with the appropriate values:
function M_A_P (theArray, callback) {
var returnArray = [];
for (var i=0; i<theArray.length; i++) {
var result = callback(theArray[i],i); // note this line
returnArray.push(result);
}
return returnArray;
}
The function M_A_P above calls a function we supply to it with two arguments, the value of one item from theArray (theArray[i]) and the index of the item (i).
Now, we can use M_A_P to process the rows:
M_A_P(rows, drawRow).join("\n");
Remember that the function drawRow will be passed in to M_A_P as the variable callback and the array rows will be passed in as the variable theArray. M_A_P then will call drawRow the way described above with two arguments.
The method Array.map() works similarly but implemented as a method of array objects instead of a function.