Is there a way to directly map each element in an array into a separate function and return the result of each function into a separate variable for that element?
For example, I have this code:
arry = ["22-03-1995", 80.5, 1.83];
born = process_date(arry[0]); // call specific function for 1st element
weight = process_weight(arry[1]); // call specific function for 2nd element
height = process_height(array[2]); // call specific function for 3rd element
...
function process_date(d) { ... }
function process_weight(w) { ... }
function process_height(h) { ... }
or such an alternative method to achieve the same in a better shorter form.
if there's only one array you want to map then you probably want something like this:
const [born, weight, height] = [
process_date(arry[0]),
process_weight(arry[1]),
process_height(array[2])
]
if there are multiple arrays then that needs its own handling, you can create a function that takes the input array and returns the mapped array:
function mapArray(arr) {
return [
process_date(arr[0]),
process_weight(arr[1]),
process_height(arr[2])
]
}
arry.forEach(arr => {
const [born, weight, height] = mapArray(arr);
// do stuff with the variables here...
})
Check out this. Might help you somehow.
You can destruct your each arrays element and assign them to a new variable. Aswel you can pass array to function as arguments.
https://javascript.info/destructuring-assignment
You could put your functions into an object. Then put your values into an array of objects, so that you can have metadata to tell the value what function it should call.
Example
const valueObjects = [{
type: "date",
value: "22-03-1995"
}, {
type: "weight",
value: 80.5
}]
const calculations = {
date: function process_date(d) {...},
weight: function process_weight(w) {...}
};
valueObjects.forEach(valueObject => {
const processType = calculations[valueObject.type];
processType(valueObject.value);
})
Hope this can help you
arry = ["22-03-1995", 80.5, 1.83];
arrayFunc = [function process_date(d) { ... }, function process_weight(w) { ... }, function process_height(h) { ... } ]
array.forEach(myFunction);
let results = []
function myFunction(item, index) {
results << arrayFunc[index](item)
}
let born, weight, height;
[born, weight, height] = results;
console.log(born);
console.log(weight);
console.log(height);
Related
function sample () {
var array = [1,2,3,4,4]
return array
}
What is the proper function call here? For example, I wanna access '1' or '2' - sample([0]) doesn't seem to work.
You need to call the function first:
function sample () {
var array = [1,2,3,4,4]
return array
}
console.log( sample()[0] );
console.log( sample()[1] );
I create some kind of "routing system" for RestfulAPI in function runUrl - on input I put url which contains some parameters (ID values) and I want to find this url in routes array, execute function given for that route with this parameters, and return that result as runUrl result.
function runUrl(url) {
return projects('f505ecfb74','5e735f505c'); // hardcoded mockup
// Question: how this function should look like ?
}
let routes = [
['/cars', cars ],
['/companies/:companyId/cars/:carId/projects', projects ],
['/companies/:companyId/room/:roomId', rooms ],
//...
];
// list of funtions to execute for given url
function cars() { return ["car1","car2"]; }
function projects(companyId,carId) { return [`proj-${companyId}`,`proj-${carId}`]; }
function rooms(companyId,roomId) { return `room-${companyId}-room-${roomId}` }
// ... (more functions)
// TEST
console.log(runUrl('/companies/f505ecfb74/cars/5e735f505c/projects'));
So far I write below function - but I have headache and it doesn't work
function runUrl(url) {
let route = routes.find( r=> url.match(r[0]) );
if(route) {
return route[1](url.match(route[0]));
}
return null;
}
The parameters values are alpha-numeric strings, parameters names in routes array start with : and then are alpha-numeric strings too. The number of parameters is arbitrary.
How function runUrl should look like?
I don't think you can do it with the match method because it's not meant to be equal between two strings, but I think I found an elegant solution to your problem, maybe it will help you :
let routes = [
['/cars', cars ],
['/companies/:companyId/cars/:carId/projects', projects ],
['/companies/:companyId/room/:roomId', rooms ],
];
function runUrl(url) {
let arrUrl = url.split('/') // it will make an array with any value after /
let route = routes.find( r=> arrUrl.length === r[0].split('/').length ); // it supposed to be equal by length
if(route) {
let params = arrUrl.filter(p => p && p.match(/\d+/)) // it will cut only the ids (string with number)
return route[1](params);
}
return null;
}
// list of funtions to execute for given url
function cars() {
return ["car1","car2"];
}
function projects(array) {
return [`proj-${array[0]}`,`proj-${array[1]}`];
}
function rooms(array) {
return `company-${array[0]}-room-${array[1]}`;
}
// ... (more functions)
// TEST
console.log(runUrl('/cars'))
console.log(runUrl('/companies/f505ecfb74/cars/5e735f505c/projects'))
console.log(runUrl('/companies/f505ecfb74/room/5e735f505c'))
Here is my proposition, similar to tomer raitz idea but use regexp to detect parameters
function runUrl(url) {
let result = undefined;
let u = url.split("/");
routes.find( ([route,func]) => {
let r = route.split("/");
if(r.length==u.length && r.every( (el,i) => /^:/.test(el) || el===u[i] ) ){
let params = u.filter((el,i)=> /^:/.test(r[i]));
result = func.call(this,...params);
return true;
}
return false;
})
return result;
}
// -----------
// TEST
// -----------
let routes = [
['/cars', cars ],
['/companies/:companyId/cars/:carId/projects', projects ],
['/companies/:companyId/room/:roomId', rooms ],
//...
];
function cars() { return ["car1","car2"]; }
function projects(companyId,carId) { return [`proj-${companyId}`,`proj-${carId}`]; }
function rooms(companyId,roomId) { return `room-${companyId}-room-${roomId}`; }
// TEST
console.log(runUrl('/companies/f505ecfb74/cars/5e735f505c/projects'));
console.log(runUrl('/cars'))
console.log(runUrl('/companies/ABC123/room/DEF5678'))
I want to take an object and an array of functions and return an array. I am trying to use the for loop here.
I have the following code below:
const fnArr = [
function firstName() {
return this.first;
},
function lastName() {
return this.last;
},
];
const obj = { first: 'Nimit', last: 'Maru' };
function callAll(obj, fnArr){
let newArray = [];
for (let i=0; i<fnArr.length; i++){
let eachFunc = fnArr[i];
return newArray.push(eachFunc.call(obj))
}
}
callAll(obj, fnArr)
My expected output is:
['Nimit', 'Maru']
But the output from my personal code is returning: 1
Question 1: What am I doing wrong here?
////////////////////////////////////////////////////////////////////////////////////////////////////////////
Additionally, the solution I was given is below:
const fnArr = [
function firstName() {
return this.first;
},
function lastName() {
return this.last;
},
];
const obj = { first: 'Nimit', last: 'Maru' };
const callAll = (obj, fnArr) => {
return fnArr.map(fn => {
return fn.call(obj);
});
};
It produces the right answer.
Question 2: In the solution code above, why do I need the call method in "return fn.call(obj)"?
A conceptual explanation of when you need or don't need call in these types of situations would be greatly appreciated.
You are returning in each loop. So after the first loop the the function ends and code doesn't execute further.
It returns 1 because push() method returns the length of the array after adding elements to it. Initally array was empty when 1 element is added it returns 1.
You don't need to necessarily use map() just push() the element(don't return). And return the newArray after loop.
const fnArr = [
function firstName() {
return this.first;
},
function lastName() {
return this.last;
},
];
const obj = { first: 'Nimit', last: 'Maru' };
function callAll(obj, fnArr){
let newArray = [];
for (let i=0; i<fnArr.length; i++){
let eachFunc = fnArr[i];
newArray.push(eachFunc.call(obj))
}
return newArray
}
console.log(callAll(obj, fnArr))
In the solution code above, why do I need the call method in "return fn.call(obj)"?
The this binding to the function depends upon how the function is called. If the function is called as the method of the object then the object will be binded to that method.
In the above code this inside your both functions will refer to window object if they are called normally. So we want this to refer the object so we use call
Why eachFunc(obj) returns [undefined, undefined]?
When you don't use call this will refer to window object. So there is not property named first and last on window object so it returns undefined
I'm trying to figure out how do I pass in an argument to a named callback function?
For example I have
var result = this.data;
var groupFilter = $("#groupSelect");
var functionFilter = $("#functionSelect");
var skillFilter = $("#skillSelect");
var uniqSkils = _(result).map('skill').uniq().map(populateDropdown(skillFilter));
var uniqFunctions = _(result).map('function').uniq().map(populateDropdown(functionFilter));
var uniqgroups = _(result).map('group').uniq().map(populateDropdown(groupFilter));
function populateDropdown(element) {
element.append($('<option>', {
value: item,
text: item
}))
}
Essentially the result contains dropdown values for three elements. I've created 3 arrays, I've then called uniq for obvious reasons, then I want to go through each array, each item and add it to the correct elements.
But I can't figure out how to pass in the element when using a named callback
You could have your populateDropdown return a closure that is bound to a particular element:
function populateDropdown(element) {
return function(item) {
element.append($('<option>', {
value: item,
text: item
}));
}
}
I am trying to reduce an array inside of an object. I am getting back
push is not a function
I have started my array as empty and created a add function to pass in as the first argument.
function add(a,b) {
return a +b;
}
var navBarArray = [];
var listArray = [];
var mapping = {
".navbar": navBarArray,
".list-group": listArray
};
I tried this approach on the mapping object but it creates errors
var mapping = {
".navbar": Math.round(navBarArray.reduce(add,0) ),
".list-group": listArray
};
However, I get push is not a function back in my console.
Below is my function that passes values to the array. I can create a variable inside the function and reduce it there. However, that limits access to my variable and will bloat my function as I continue.
Object.keys(mapping).forEach(function(selector) {
$(selector).hover(function(evt) {
console.log('mapping',mapping);
console.log('selector',selector);
enteredTime = new Date();
}, function() {
var ctime = new Date();
var time = (ctime.getTime() - enteredTime.getTime())/1000;
mapping[selector].push(time);
// *********** this works but not where I need it to*******
var reduce = Math.round(navBarArray.reduce(add,0) );
console.log(reduce);
});
})
Change your mapping object so it has separate places for the array and total:
var mapping = {
".navbar": {
total: 0,
times: []
},
".list-group": {
total: 0,
times: []
}
}
Then you do mapping[selector].times.push(time), and put the total with:
mapping[selector].total = mapping[selector].times.reduce(add, 0);