Javascript generate logical array based on condition - javascript

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]

Related

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);

Can I map a function with more then one argument?

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))

JS array problems - slice array 'b' and 'a' is sliced too

I have 2 arrays: A and B, when I change one both change. Is there a way to edit one without changing the other one.
a = [[0,0,0,0,0],[0,0,0,0,0]]
b = [[1,2,3,4,5],[6,7,8,9,10]]
a = b.slice(0)
a[0][0] = 10
console.log(a) /* [[10,2,3,4,5],[6,7,8,9,10]] */
console.log(b) /* [[10,2,3,4,5],[6,7,8,9,10]] */
The a is fine but I need b to stay [[1,2,3,4,5],[6,7,8,9,10]]
When you do splice, you change the reference of a and b, however, the reference of arrays in array b still share references, hence, update your code to following. Use Array.map
a = [[0,0,0,0,0],[0,0,0,0,0]]
b = [[1,2,3,4,5],[6,7,8,9,10]]
a = b.map(x => [...x])
a[0][0] = 10
console.log(a) /* [[10,2,3,4,5],[6,7,8,9,10]] */
console.log(b) /* [[1,2,3,4,5],[6,7,8,9,10]] */
You can use map to slice each array.
a = [[0,0,0,0,0],[0,0,0,0,0]]
b = [[1,2,3,4,5],[6,7,8,9,10]]
a = b.map(o=>o.slice(0));
a[0][0] = 10
console.log(a);
console.log(b);
Doc: map()
You take a shallow copy with Array#slice, which means nested arrays are taken by their object reference.
You could use Array#map with a check for arrays and map these recursively.
const deep = a => Array.isArray(a) ? a.map(deep) : a;
var a = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
b = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]];
a = b.map(deep);
a[0][0] = 10;
console.log(a);
console.log(b);
.as-console-wrapper { max-height: 100% !important; top: 0; }
slice(), like Object.freeze() have a shallow scope, so this works:
var a = [1,2,3,4];
var b = a.slice(0);
a[0] = 10;
console.log(b); // [1, 2, 3]
console.log(a); // [10, 2, 3, 4]
But this doesn't work:
var a = [[0,0,0,0,0],[0,0,0,0,0]]; //multidimensional!
var b = [[1,2,3,4,5],[6,7,8,9,10]];
a = b.slice(0);
a[0][0] = 10;
console.log(a);
console.log(b);
Then, the key is go deep with slice(), for or something, Here an example using for:
var a = [];
for (var i = 0, len = b.length; i < len; i++) {
a[i] = b[i].slice();
}
Keep in mind that const won't work:
var a = [[0,0,0,0,0],[0,0,0,0,0]];
const b = [[1,2,3,4,5],[6,7,8,9,10]];// doesn't work
var a = b.slice(0);
a[0][0] = 10; // a changes b
console.log(a);
console.log(b);

Move every other value from array into a new array

I have two one-dimensional arrays, a and b. a has values and b is empty. The length of a is an even number. I'd like to remove every other value from a and move them to b, in the same order as they were placed in a.
var a = [1, 2, 3, 4, 5, 6], b = [];
becomes
var a = [1, 3, 5], b = [2, 4, 6];
I figured that filter would do the trick but I'm not that happy with the performance of it since the average length of a is 300-400.
b = a.filter((i, idx) => {
return idx % 2 == 0;
});
a = a.filter((i, idx) => {
return idx % 2 == 1;
});
I've also been looking at lodash to see if that library had anything that might help me and the only function that's near what I'm looking for is _.chunk(array, \[size=1\]).
I appreciate any and all help to help me figure out a better, faster way to do this.
Since you mentioned lodash you could do this with _.partition:
let a = [1, 2, 3, 4, 5, 6];
let b = [];
let i = -1;
[a, b] = _.partition(a, (item) => i++ % 2);
console.log(a);
console.log(b);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
Partition's predicate is the identity function, which doesn't include the index of the item, so this comes with a compromise of an external index i.
Of course, you could always wrap this functionality into it's own function:
const splitEvenOdd = (array, i = -1) => _.partition(array, (item) => i++ % 2);
let a = [1, 2, 3, 4, 5, 6];
let b = [];
[a, b] = splitEvenOdd(a);
console.log(a);
console.log(b);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
Vanilla JS ES5, simple and clean.
var a = [1, 2, 3, 4, 5, 6], b = [];
for(var i = a.length-1; i >= 0; i--) {
if(i % 2 === 1) {
b.unshift(a.splice(i, 1)[0])
}
}
Basically, it is iterating through a backwards, and if the condition is true splicing the item und adding it as first item of b.
To loop through the source once, the values can be added to a specific array depending on the index. For example:
const source = [1, 2, 3, 4, 5, 6];
let arrs = [[],[]];
for(let i = 0; i< source.length; i++)
arrs[i%2].push(source[i]);
let [a,b] = arrs;
console.log(a);
console.log(b);
Alternatively, if it's important to alter the original arrays, a can be filled in a direct iteration, since the index being processed is always ahead of the one being filled:
let a = [1, 2, 3, 4, 5, 6], b= [];
for(let i = 0; i< a.length; i++)
(i % 2 ? b : a)[Math.floor(i/2)] = a[i];
a.splice(a.length/2);
console.log(a);
console.log(b);
The best performance you can get for this is 0(n) or linear time since you have to iterate through the entire array. What may help is reducing the number of loops
var a=[];
var b=[];
function splitArray(arr)
{
for (var i=0;i<arr.length;++i)
{
if (arr[i]%2 == 0)
b.push(arr[i]);
else
a.push(arr[i]);
}
}
What this does is reduces the number of times you have to iterate through the original array from 2 to 1

Python for loop inside brackets syntax

So I'm trying to convert this Python function into Javascript. I'm new to Python, so some of the syntax is difficult for me to cipher. Here's both the original code and my attempt at JS-conversion. I know I've interpreted something wrong, because what I have now is an infinite loop.
Python:
graph = [[0,1,0,0,1,0],[1,0,1,0,1,0],[0,1,0,1,0,0],[0,0,1,0,1,1],[1,1,0,1,0,0],[0,0,0,1,0,0]]
def N(vertex):
c = 0
l = []
for i in graph[vertex]:
if i is 1 :
l.append(c)
c+=1
return l
def bronk(r,p,x):
if len(p) == 0 and len(x) == 0:
print r
return
for vertex in p[:]:
r_new = r[::]
r_new.append(vertex)
p_new = [val for val in p if val in N(vertex)] #this and
x_new = [val for val in x if val in N(vertex)] #this part was particularly difficult to understand
bronk(r_new,p_new,x_new)
p.remove(vertex)
x.append(vertex)
bronk([], [0,1,2,3,4,5], [])
And here's my attempt at its conversion to JS:
'use strict';
const graph = [[0,1,0,0,1,0],[1,0,1,0,1,0],[0,1,0,1,0,0],[0,0,1,0,1,1],[1,1,0,1,0,0],[0,0,0,1,0,0],];
function N(vertex){
let c = 0;
const l = [];
for (let i in graph[vertex]){
if (i){
l.push(c);
c++;
}
}
return l;
}
function bronk(r,p,x){
if (p.length == 0 && x.length == 0){
console.log(r);
return;
}
for (let vertex in p.slice(0)){
const r_new = r.slice(0);
r_new.push(vertex);
const p_new=p.filter(val=>~~N(vertex).indexOf(val)); //hereĀ“s my best guess...
const x_new=x.filter(val=>~~N(vertex).indexOf(val));
bronk(r_new, p_new, x_new);
p=p.splice(vertex,1);
x.push(vertex);
}
}
bronk([], [0,1,2,3,4,5], []);
I got the Python code from this question.
Edit: I'm working in an ES6 environment.
They're both List comprehensions in python
The closest you can get to a list comprehension in python in Javascript (Without ES6, babel and its relations) is to use Array.Map (Similar to python's map)
Example in python
>>> l = [2, 4, 6, 8, 10, 12]
>>> [int(i / 2) for i in l]
[1, 2, 3, 4, 5, 6]
In Javascript:
l = [2, 4, 6, 8, 10, 12]
l.map(function(i){ return i / 2 });
[1, 2, 3, 4, 5, 6]
With Arrow functions in ES6, you can get rid of the function(){}
l.map(x => x/2)
[2, 4, 6, 8, 10, 12]
So your code should look like this
const p_new = p.map(function(i){ if(i in N(vertex)){ return i } });
const x_new = x.map(function(i){ if(i in N(vertex)){ return i } });
It would be better to use:
p.filter(val => graph[vertex][val])
As this cuts out the useless Array creation that N does.
Also ~~ doesn't properly convert -1 to false and 0 .. n to true. Use !!~ instead.

Categories