the every method does not work in javascript - javascript

Firstly, the .includes method does not work with my framework, so I omit this here.
I have checkIn(el,ar) function to check if el in ar like this:
function checkIn(el){
var check = false;
for (i = 0; i < ar.length; i++){
if(el === ar[i]){
check = true;
break;
};
};
return check;
};
it works normaly. Then I want to use the .every method to check if every element of a given array is in another given array
var x = [1,2,3];
var y = [1,2,3,4,5];
var check = x.every(checkIn(y))
check needs to be true, but it doesn't work?

.every accepts a callback for which the first parameter is an element of the array being iterated over. If you want to be able to use
x.every(checkIn(y))
then checkIn should return a function that can then be used as the callback:
function checkIn(containingArr) {
return item => containingArr.includes(item);
};
var x = [1, 2, 3];
var y = [1, 2, 3, 4, 5];
console.log(x.every(checkIn(y))); // every item in x is in y; true
console.log([0].every(checkIn(y))); // 0 is not in y; false
Or, to use something similar to your for loop:
function checkIn(ar) {
return el => {
var check = false;
for (i = 0; i < ar.length; i++) {
if (el === ar[i]) {
check = true;
break;
};
};
return check;
};
}
var x = [1, 2, 3];
var y = [1, 2, 3, 4, 5];
console.log(x.every(checkIn(y)));
console.log([0].every(checkIn(y)));

First off, your checkIn(el,ar) does only take el so if you're not getting an error you're accessing a global or out-of-scope variable ar that may hold data that doesn't make sense in that context.
If you simply want to check if an array contains a specific value there is a really simple way to do it:
[1,2,3].includes(3) //true
[1,2,3].includes(6) //false
And to extrapolate to a whole array using .every requires you to pass a lambda or function, not just a function call, like so:
var xs = [1, 2, 3];
var ys = [1, 2, 3, 4, 5];
xs.every(x => ys.includes(x))
where x => ys.includes(x) is shorthand for function(x){return ys.includes(x)}
or using your checkIn(el,ar)
xs.every(x => checkIn(x,ys))

Function checkIn looks redundant.
function checkIn(el, ar) {
let check = false;
for (let i = 0; i < ar.length; i++) {
if (el === ar[i]) {
check = true;
break;
};
};
return check;
};
Why not use Array.prototype.includes?
BTW, the first parameter of the function every should be a function but you pass the result of checkIn, which type is boolean.
We can do like this.
x.every((e) => y.includes(e))

Related

Why changing the "if" condition give different answers when I use === instead of !==?

The function checks if array elements are same, if they are same it should return true.
When I use the function below, it gives the correct result.
var arr = [1, 2, 3, 4];
function isUniform(arr) {
var store = arr[0];
for (var i = 0; i < arr.length; i++) {
if (arr[i] !== store) {
return false;
}
}
return true;
}
console.log(isUniform(arr));
But when I use the function like this i.e; changing the if condition, it returns false
var arr = [1, 2, 3, 4];
function isUniform(arr) {
var store = arr[0];
for (var i = 0; i < arr.length; i++) {
if (arr[i] === store) {
return true;
}
}
return false;
}
console.log(isUniform(arr));
The problem is that your snippet is returning true if one of the next values are the same as arr[0], see the below example:
var arr = [1, 1, 3, 1, 1];
function isUniform(arr) {
var store = arr[0];
for (var i = 0; i < arr.length; i++) {
if (arr[i] === store) {
return true;
}
}
return false;
}
console.log(isUniform(arr));
Here the function returns true as soon as the for loop starts, since arr[0] is store
What you should use is Array#every() which checks if all elements match certain criteria:
var arr = [1, 1, 3, 1, 1];
var arr2 = [1,1,1,1,1,1,1];
function isUniform(arr) {
return arr.every(e => e === arr[0]);
}
console.log(isUniform(arr));
console.log(isUniform(arr2));
The firts loop is giving the rigth answer because the elements in the list are not the same, the problem with the second loops is that it checks each element in the list and when i found a element equals to the array[0] (in this case (1)) it will return true which can't be.
The second loops should be:
var arr = [1, 2, 3, 4];
function isUniform(arr) {
var store = arr[0];
var response = false;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === store) {
resonse = true;
continue;
}
return response;
}
return response;
}
console.log(isUniform(arr));
Cause it will return true if the first element is the same. It won't check all elements while the second will return true if all elements are the same if one of the elements is not the same it returns false.
The probably shortest approach to this is:
(new Set(array)).size === 1
The second code snipped does not check if all elements are equal to store, it returns true if at least one is equal to store.
And the first one returns false if all of the elemens are not equal to store, and as of that true if all of them are equal to store, but to be previces it does not test if all elements equal store it's only a logical conclusion in this case.
It returns true ... You can also consider doing...
arr.includes(arr[0]) // returns true

Evaluating an Array for Uniformity

I am trying to evaluate an array for uniformity. I.e. var num =[1,1,1,1,1,] // true or var num =[1,1,2,1,1] = //false. It could also be for an array of strings. What I am trying to do is evaluate the whole array and return a single "true" or "false". My code so far evaluates each item in the array and returns the result for each item. I'm very new to coding and taking classes online and working through problems without cheating!
var num = [1,1,3,1,1];
var first = num[0];
num.forEach(function (num, i) {
if(first === num){
console.log(true);
} else {
console.log(false);
}
});
You're on the right track. Instead of logging a true or false for each answer, create a variable to store the overall answer, then print that when you're done. Something like this:
var num = [1,1,3,1,1];
var first = num[0];
var ans = true;
num.forEach(function (n) {
if(first !== n){
ans = false;
}
});
console.log(ans);
Using .some()
var num = [1,1,3,1,1];
var notUni = num.some(function(val, idx, arr){
return val != arr[0]; // (If arr[0] (1) is the base you're interested in)
});
console.log( notUni ); // true
P.S: some will exit as soon it finds a (true) mismatch.
Use Array.prototype.every() function
var num = [1, 1, 3, 1, 1];
var result = num.every(n => n == num[0]);
The every() method tests whether all elements in the array pass the test implemented by the provided function.
var num = [1, 1, 1, 1, 1];
var result = num.every(n => n == num[0]);
document.write(result);

Concise way to get indexes of array elements that are contained in another array?

I have two arrays, a and b, e.g.
var a = [1,2,3,4];
var b = [2,4];
I want to get the indexes of the elements of a that are contained in b. I could use a loop, like
var ii = [];
for (var i=0; i < x.length; i++)
{
if (y.indexOf(x[i]) >= 0)
ii.push(i);
};
This works. But coming from the R language where this would simply be which(a %in% b), I suppose there will be more concise ways to get what I want in JS. Suggestions?
TIA :)
You can make it shorter by using Array.map
var idx = b.map(function(n){ return a.indexOf(n) }).filter(function(n){
return n != -1
})
A solution using the Array.reduce method
var a = [1,2,3,4];
var b = [2,4];
var idxs = b.reduce(function(l, r, idx) {
var i = a.indexOf(r);
return i > -1 ? (l.push(i), l) : l;
}, []);
console.log(idxs);
Lodash also offers tools that could make this easy. If you fancy using external libraries:
var a = [1,2,3,4];
var b = [2,4];
var intersection = _.intersection(a,b);
_.forEach(intersection, function(item){
console.log(a.indexOf(item));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
But a pure vanilla solution could looks like:
var a = [1,2,3,4];
var b = [2,4];
function intersection(a, b)
{
var ai=0, bi=0;
var result = new Array();
while( ai < a.length && bi < b.length )
{
if (a[ai] < b[bi] ){ ai++; }
else if (a[ai] > b[bi] ){ bi++; }
else /* they're equal */
{
result.push(a[ai]);
ai++;
bi++;
}
}
return result;
}
var intersect = intersection(a,b);
intersect.forEach(function(item){
console.log(a.indexOf(item));
});
There will always be some form of loop, either written outright or implied with a call to Array.map() or the like. There's not much of a way around that.
You shouldn't have to write that code, though. Libraries like Lodash and Underscore have a method called intersection() which does the bulk of this -- potentially with more than two arrays:
_.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
// → [1, 2]
For the specific case of getting the indexes from a, you can chain the output of intersection() into map():
var a = [1,2,3,4];
var b = [2,4];
var result = _.intersection(a, b).map(function (v) {
return a.indexOf(v);
});
console.log(result);
// → [1, 3]
This works by mapping array a to return its index or an empty string-
filtering the map for Numbers returns only the indexes.
But your original script is more efficient, which is worth a few bytes download.
var a = [1,2,3,4];
var b = [2,4];
var a_in_b=a.map(function(itm,i){ return b.indexOf(itm)!=-1? i:''}).filter(Number);
/* a_in_b value: (Array) [1,3]; */

Cycle function in Javascript

I new to Javascript and I am looking for a cycle function. Here's Clojure's implementation I am trying to find a cycle function that infinitely loops/recurses through values of an array. I was hoping to find something like this in the underscore library, but I could not find anything suitable. Ideally I would like to use something like this:
_.head(_.cycle([1,2,3]), 100)
This function would return an array of 100 elements:
[1,2,3,1,2,3,1,2,3,1,2,3,...]
Is there a function like this I can use in Javascript? Here's my feable attempt, but I can't seem to get it to work:
arr = [1,2,3,4,5,6,7,8,9];
var cycle = function(arr) {
arr.forEach(function(d, i) {
if (d === arr.length)
return d
d == 0
else {return d}
});
};
cycle(arr);
You could do something like:
var cycle = function(array, count) {
var output = [];
for (var i = 0; i < count; i++) {
output.push(array[i % array.length]);
}
return output;
}
An implementation of Clojure's cycle :
function cycle(input) {
return function (times) {
var i = 0, output = [];
while (i < times) {
output.push(input[i++ % input.length]);
}
return output;
};
}
Usage examples :
var chars = cycle(['a', 'b']);
chars(0) // []
chars(1) // ["a"]
chars(3) // ["a", "b", "a"]
cycle([1, 2])(3) // [1, 2, 1]
An implementation of Clojure's take :
function take(length, input) {
return typeof input === 'function'
? input(length)
: input.slice(0, length);
}
Usage examples :
take(3, [1, 2, 3, 4]) // [1, 2, 3]
take(3, cycle([1, 2])) // [1, 2, 1]
Both implementations probably do not fit exactly Clojure's versions.
The problem with trying to emulate purely functional in JavaScript is eagerness: JavaScript doesn't have lazy evaluation and hence you can't produce infinite arrays in JavaScript. You need to define a lazy list in JavaScript. This is how I usually do it:
function cons(head, tail) {
return cont({
head: head,
tail: tail
});
}
function cont(a) {
return function (k) {
return k(a);
};
}
The cons function is similar to the cons function in LISP or the : constructor in Haskell. It takes an element and a list and returns a new list with the element inserted at the beginning of the list. The cont function creates a continuation (really useful for reifying thunks to emulate lazy evaluation).
Creating a list using cons is very simple:
var list = cons(1, cons(2, cons(3, cons(4, cons(5, null)))));
var array = [1, 2, 3, 4, 5];
The above list and array are equivalent. We can create two function to convert arrays to lists and vice-versa:
function toList(array) {
var list = null, length = array.length;
while (length) list = cons(array[--length], list);
return list;
}
function toArray(list) {
var array = [];
while (list) {
list = list(id);
array = array.concat(list.head);
list = list.tail;
}
return array;
}
function id(x) {
return x;
}
Now that we have a method of implementing lazy lists in JavaScript let's create the cycle function:
function cycle(list) {
list = list(id);
var head = list.head;
var tail = join(list.tail, cons(head, null));
return function (k) {
return k({
head: head,
tail: cycle(tail)
});
};
}
function join(xs, ys) {
if (xs) {
xs = xs(id);
return cons(xs.head, join(xs.tail, ys));
} else return ys;
}
Now you can create an infinite list as follows:
var list = cycle(toList([1,2,3]));
Let's create a take function to get the first 100 elements of the list:
function take(n, xs) {
if (n > 0) {
xs = xs(id);
return cons(xs.head, take(n - 1, xs.tail));
} else return null;
}
We can now easily get an array of 100 elements with [1,2,3] repeating:
var array = toArray(take(100, list));
Let's see if it works as expected: http://jsfiddle.net/TR9Ma/
To summarize, lazy functional programming in JavaScript is not as much fun as it is in purely functional languages like Haskell. However with a little bit of effort you can make it work.
Here is a slightly more compact version:
function cycle(arr, count) {
for (var i = 0, out = []; i < count; i++) {
out.push(arr[i % arr.length]);
}
return out;
}
And a JSFiddle (outputs the results to the console):
http://jsfiddle.net/2F9hY/1/
Basically just loops through count number of times, getting the i % arr.length item and adding it to the array.
This function should work. You can put the mod operation to good use here.
var cycle = function(input, n) {
var output = [];
for (var i = 0; i < n; i++) {
var j = i % input.length;
output.push(input[j]);
}
return output;
}
Here's a working fiddle: http://jsfiddle.net/K6UhS/1/
Also, I wouldn't introduce a whole library just for this function!
The wu library includes a cycle function which does this:
wu.cycle([ 1, 2, 3 ]).take(10).toArray() // [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 1 ]
If you don't need support for iterators/streams/infinite lists, and just want a function that cycles through an array's values, lei-cycle provides a much more lightweight solution:
const Cycle = require('lei-cycle')
let c = Cycle([ 1, 2, 3 ])
console.log(c()) // 1
console.log(c()) // 2
console.log(c()) // 3
console.log(c()) // 1
// ...
function cycle(array) {
let result = [...array]
result[Symbol.iterator] = function* () {
while (true)
yield* this.values()
}
return result
}
class Cycle {
constructor(array) {
this.array = array;
}
next () {
var x = this.array.shift();
this.array.push(x);
return x;
}
}
const cycle = new Cycle(['a','b','c']);
console.log(cycle.next()); // returns "a"
console.log(cycle.next()); // returns "b"
console.log(cycle.next()); // returns "c"
console.log(cycle.next()); // returns "a"
console.log(cycle.next()); // returns "b"
...

Javascript matrix addition of an arbitrary number of arrays' values, without using array.map()

I'm trying to build a helper function for my AngularJS app (but the solution doesn't have to use angular.forEach). The function should take an arbitrary number of arrays with same length and add the values together to form an new array, e.g.:
a = [1, 2, 3];
b = [4, 5, 6];
result = [5, 7, 9];
I'm trying to not use array.map() or sylvesterjs for IE8 compatibility. I'm stuck on looping through arguments as javascript doesn't seem to like nesting functions within a for loop. Code so far:
function arrayAdd () {
// make sure all args have same length
var totalLen = 0;
angular.forEach(arguments, function (arg) {
totalLen += arg.length;
});
var avgLen = totalLen / arguments.length;
if (avgLen === arguments[0].length) {
var arrNew = mkArray(0, arguments[0].length);
// helper function to make an empty array, not shown here
// need to refactor below with loop for unlimited # of args
angular.forEach(arguments, function (arg, i) {
arrNew[0] += arg[0];
});
angular.forEach(arguments, function (arg, i) {
arrNew[1] += arg[1];
});
return arrNew;
} else {
throw 'arrayAdd expects args with equal length';
}
}
Thanks!
No need for map, you only need to keep track of the arrays as you total them.
(This does not check that the arrays have the same length-)
function sumArrayElements(){
var arrays= arguments, results= [],
count= arrays[0].length, L= arrays.length,
sum, next= 0, i;
while(next<count){
sum= 0, i= 0;
while(i<L){
sum+= Number(arrays[i++][next]);
}
results[next++]= sum;
}
return results;
}
var a= [1, 2, 3], b= [4, 5, 6], c= [1, 2, 3];
sumArrayElements(a, b, c)
/* returned value:(Array)
6, 9, 12
*/
Why don't you just add it to the array prototype if it doesn't exist?
if (!('map' in Array.prototype)) {
Array.prototype.map= function(mapper, that /*opt*/) {
var other= new Array(this.length);
for (var i= 0, n= this.length; i<n; i++)
if (i in this)
other[i]= mapper.call(that, this[i], i, this);
return other;
};
}
Figured it out, didn't need array.map(). Writing the arrays and loops out on paper helped. Hope this is helpful for someone else.
function arrayAdd () {
// ensure all args have same length
var totalLen = 0;
angular.forEach(arguments, function (arg) {
totalLen += arg.length;
});
var difLen = arguments[0].length === totalLen / arguments.length;
if (difLen) {
var arrNew = mkYrArray(0, arguments[0].length, 0);
// helper function to make an empty array, not shown here
angular.forEach(arguments, function (arr, i1) {
// each loop is an array from arguments
angular.forEach(arr, function (arrValue, i2) {
// each loop is a value from array
arrNew[i2] += arrValue;
});
});
return arrNew;
} else {
throw 'arrayAdd expects args w/ equal len';
}
}

Categories

Resources