Can I map a function with more then one argument? - javascript

In EE (Google Earth Engine Javascript API) I can do
var listOfNumbers = [0, 1, 1, 2, 3, 5];
print('List of numbers:', listOfNumbers);
var add_ten = function(n) {
var m = n + 10;
return m;
}
var listOfNumbers_ = listOfNumbers.map(add_ten);
print('List of numbers:', listOfNumbers_);
What if I want to add x (or another value) instead of 10? Like
var listOfNumbers = [0, 1, 1, 2, 3, 5];
print('List of numbers:', listOfNumbers);
var add_x = function(n, x) {
var m = n + x;
return m;
}
var listOfNumbers_ = listOfNumbers.map(add_x);
print('List of numbers:', listOfNumbers_);
How do I pass that x?
I tried
var listOfNumbers_ = listOfNumbers.map(add_x(100));
print('List of numbers:', listOfNumbers_);
But got NaN is not a function.
Also tried
var listOfNumbers_ = listOfNumbers.map(add_x, 100);
print('List of numbers:', listOfNumbers_);
Then got the following interesting result (which I don't understand)
0,2,3,5,7,10

If you don't want to change your current function, then you can use partial application via Function#bind to supply one argument to it but not the other:
var listOfNumbers = [0, 1, 1, 2, 3, 5];
var add_x = function(n, x) {
var m = n + x;
return m;
}
var add_10 = add_x.bind(null, 10);
var listOfNumbers_ = listOfNumbers.map(add_10);
console.log(listOfNumbers_);
Or even even:
var listOfNumbers_ = listOfNumbers.map(add_x.bind(null, 10));
Alternatively, you can use currying:
var listOfNumbers = [0, 1, 1, 2, 3, 5];
var add_x = function(n) {
return function (x){
var m = n + x;
return m;
}
}
var add_10 = add_x(10);
var listOfNumbers_ = listOfNumbers.map(add_10);
console.log(listOfNumbers_);
Or even:
var listOfNumbers_ = listOfNumbers.map(add_x(10));
You can shorten the curried definition using arrow functions:
var add_x = n => x => n+x;

The array sum makes perfect sense when you look at the function signature of Array#map, as the first two parameters provided to the callback function are the element and the index iterated.
You have at least two choices:
Function#bind, to prefix the initial argument n and let x be the element from the array,
Anonymous function expression:
E.g.
const arr = [0, 1, 1, 2, 3, 5];
const r1 = arr.map(add_x.bind(null, n));
const r2 = arr.map(x => add_x(n, x));

Here is a method using currying:
var listOfNumbers = [0, 1, 1, 2, 3, 5];
console.log('List of numbers:', listOfNumbers);
var add_x = (n) => (x) => {
return n + x;
}
var listOfNumbers_ = listOfNumbers.map(add_x(100));
console.log('List of numbers:', listOfNumbers_);
Note the add_x variable is set to a function that is called with the second value as the parameter.
When used with the .map() method, the first value comes from the array and the second is provided as the parameter to the function. It is the equivalent of calling it like this:
add_x(1)(100)

You can simply write a new function and pass it to the .map() method:
function mapFn(value) { return add_x(value, 100) }
listOfNumbers.map(mapFn)
You can use arrow function syntax to make it even simpler:
listOfNumbers.map(value => add_x(value, 100))

Related

How do i rewriting a function code javascript

A function that returns a new array that contains the product of each pair of numbers from the arguments that have the same index.
var a = [3, 5, 7];
var b = [9, 10, 11];
a.map(function(x, index) { //here x = a[index] //how do i write this as function name(){}
console.log(b[index] * x);
});
var a = [3, 5, 7];
var b = [9, 10, 11];
let c = [];
function name(a, b) {
a.map(function(x, index) {
let result = b[index] * x;
c.push(result);
}
}
name(a, b);
console.log(c) // this will show a new array with the results
this way
var a = [3, 5, 7];
var b = [9, 10, 11];
function myFunction(x,index)
{
return (b[index] * x);
}
var c = a.map(myFunction);
console.log( c )
You need to return the new value from the map callback.
var a = [3, 5, 7];
var b = [9, 10, 11];
const res = a.map((x,index)=>b[index] * x);
console.log(res);
The specs of .map() say that:
The map() method creates a new array populated with the results of
calling a provided function on every element in the calling array.
var a = [3, 5, 7];
var b = [9, 10, 11];
function name(value_of_array_a, index_of_array_b) {
return b[index_of_array_b] * value_of_array_a;
}
var result = a.map(name);
console.log(result);

how to add 3 different number to the i, i+1 and i+2 of my array

I want to know how can I add 3 different number to the 3n, 3n+1 and 3n+2 indices. I mean for example I have following array :
var arr = [1,1,1,2,2,2,3,3,3]
and then I want add the (3n)th to 5 and then I want add (3n+1)th of an array to 2 and (3n+2) to 3,
I mean the final array I want to be like following result array:
var result = [6,3,4,7,4,5,8,5,6]
and I try to do it as following code:
// arr = [1,1,1,2,2,2,3,3,3]
let res = [];
for (let i = 0; i < arr.length; i++) {
res.push([arr[i*3] * 5,
arr[(i*3)+1] *2,
arr[(i*3)+2] *3])
}
This should do the trick:
var arr = [1,1,1,2,2,2,3,3,3],
add = [5,2,3], res=[];
// result = [6,3,4,7,4,5,8,5,6]
for (let i=0;i<arr.length;i+=add.length) add.forEach((v,j)=>res[i+j]=arr[i+j]+v);
console.log(JSON.stringify(res))
An alternative and even shorter solution (similar to #Robin's answer) would be:
var arr = [1,1,1,2,2,2,3,3,3],
add = [5,2,3], res=[];
res=arr.map((v,i)=>v+add[i%add.length]);
console.log(JSON.stringify(res))
( I noticed #Nina came up with a very similar answer ...)
You can simply use map, making use of the fact that its function argument takes the current index an optional second argument:
var arr = [1,1,1,2,2,2,3,3,3];
var result = arr.map((num, idx) => {
switch (idx % 3) {
case 0:
return num + 5;
case 1:
return num + 2;
case 2:
return num + 3;
}
});
console.log(result);
You could mapp the array directly by taking a closure over an index for the values array for adding.
var array = [1, 1, 1, 2, 2, 2, 3, 3, 3],
add = [5, 2, 3],
result = array.map((i => v => v + add[i++ % add.length])(0));
console.log(...result);

mean of two arrays in javascript

I have:
x = [1,2,3]
y = [2,3,4]
I want to find the average so the result is:
z = [1.5,2.5,3.5]
Thanks in Advance.
Use map to iterate and return the mean value
var output = x.map((s,i)=> (s+y[i])/2);
Demo
var x = [1, 2, 3];
var y = [2, 3, 4];
var output = x.map((s, i) => (s + y[i]) / 2);
console.log(output);
You could take an arbitrary count of arrays and sum only the part for the result.
var x = [1, 2, 3],
y = [2, 3, 4],
result = [x, y].reduce((r, a, i, o) => a.map((b, j) => (r[j] || 0) + b / o.length), []);
console.log(result);

Creating a function that combines all elements of N number of arrays using apply

I'm practicing higher order functions by actually hard coding what's going on under the hood. I'm stumped by this questions because I have a very limited understanding of how apply() and arguments work.
This is my expected result:
mapN([1, 2, 3], [4, 5, 6], [2, 2, 2], function(a, b, c) {
return (a * b) + c;
});
// => [6, 12, 20]
mapN([1, 2, 3], function(x) { return x * x; }) // => [1, 4, 9]
I manually coded out a forEach function and a Map function like this ( I know this isn't necessary but I am trying to truly understand what's going on under the hood with HOFs):
function each(coll, f) {
if (Array.isArray(coll)) {
for (var i = 0; i < coll.length; i++) {
f(coll[i], i);
}
} else {
for (var key in coll) {
f(coll[key], key);
}
}
}
function map(array, f) {
var acc = [];
each(array, function(element, i) {
acc.push(f(element, i));
});
return acc;
}
However, I have no idea where to go from here. How do I use apply and arguments together ? I've spent an hour trying to figure it out ? :
function mapN(f){
var newArray = [];
var args = Array.prototype.slice.apply(arguments);
f.apply(newArray, args)
return newArray;
}
You should loop through all the arrays to generate the parameter array that you will use for apply:
function mapN () {
var args = Array.from(arguments), // arguments passed to `mapN`
callback = args.pop(), // the callback function is the last argument
result = []; // the result array
if(!args.length) return result; // if there is no arrays passed as arguments, then return the empty array
for(var i = 0, len = args[0].length; i < len; i++) { // for each i from 0 to the length of one of the arrays
var params = args.map(arr => arr[i]); // get the i-th element of every array in args to use as parameters to the callback
result.push(callback.apply(null, params)); // call the callback with the params array and store the result
}
return result;
}
Note: if the arrays could be of different lengths, then you may want to change:
len = args[0].length
to:
len = Math.max.apply(null, args.map(arr => arr.length));
so len will be equal to the maximum length possible.
Examples:
function mapN () {
var args = Array.from(arguments),
callback = args.pop(),
result = [];
if(!args.length) return result;
for(var i = 0, len = args[0].length; i < len; i++) {
var params = args.map(arr => arr[i]);
result.push(callback.apply(null, params));
}
return result;
}
var a = mapN([1, 2, 3], [4, 5, 6], [2, 2, 2], function(a, b, c) {
return (a * b) + c;
});
console.log(a);
// => [6, 12, 20]
var b = mapN([1, 2, 3], function(x) { return x * x; });
console.log(b);
// => [1, 4, 9]

Javascript generate logical array based on condition

Coming from a matlab background, I am trying to replicate the following scenario in Javascript
A = [1, 2, 3, 4, 5];
B = 4;
C = A == B;
answer => C = [0, 0, 0, 1, 0]
In other words, it generates a logical array where only the value compared is set to 1. I can do this using a loop but I was wondering if there a 1 liner solution to this in javascript?
You can use the map() function to do something similar to what you were looking for:
var A = [1, 2, 3, 4, 5];
var B = 4;
var C = function (x) { return +(x === B); };
var answer = A.map(C);
var C = x => +(x === B); would look cleaner, but that's ES6 code (experimental).
About the fanciest you could get would be
var C = A.map(function(v) { return v == B ? 1 : 0; });
That's supported in newer JavaScript runtime systems.
In JavaScript it'd probably be more idiomatic to prefer a result array containing boolean values:
var C = A.map(function(v) { return v == B; });
There's not a one-liner, but using Array.map can get you pretty close to what you want:
var a = [1, 2, 3, 4, 5];
var b = 4;
var c = a.map(function(item) { return item === b? 1: 0; });
console.log(c);
Fiddle
Note map isn't supported by older browsers, the MDN link above has polyfil code or you can include any number of libraries that provide something equivalent (e.g. jQuery has a .map() function).
You could write your own function :
function equals(a, b) {
var result = [];
while (result.length < a.length) {
result.push(+(a[result.length] == b));
}
return result;
}
var A = [1, 2, 3, 4, 5];
var B = 4;
var C = equals(A, B); // [0, 0, 0, 1, 0]

Categories