Turning for loop into forEach JavaScript - javascript

Working on a function that verifies if each number in an array is true or false and returns the first true number.
Have a working solution with a for loop as follows:
function findElement(arr, func) {
var num;
for (var a = 0; a < arr.length; a++) {
if (func(arr[a])) {
num = arr[a];
return num;
}
}
return num;
}
findElement([1, 3, 5, 8, 9, 10], function(num) {
return num % 2 === 0;
})
// Should return 8
But I'm trying (in order to get my head around forEach better) to convert it into a forEach loop.
This is where I am so far, but I don't see how to actually return the num out of the loop after it's been established that the function result is true:
function findElement(arr, func) {
if (arr.forEach(func) === true) {
return num;
}
}
findElement([1, 2, 3, 4], num => num % 2 === 0);

Not sure how to use forEach but you could use array.prototype.filter:
function findElement(arr, func) {
return arr.filter(func)[0];
}
#cdhowie suggested the use array.prototype.find in order to need the usage of [0].
function findElement(arr, func) {
return arr.find(func);
}
Obviously, that is just a guess because it may raise an error if no item in the array meets the requirements of func.
If you still are looking about use forEach maybe you could do something like this:
function findElement(arr, func) {
matches = []
arr.forEach((item) => {
if (func(item)) {
matches.push(item)
}
});
return matches[0];
}
Or:
function findElement(arr, func) {
match = null
arr.forEach((item) => {
match = (match == null && func(item)) ? item : match
});
return match;
}
Again, you will have to check how to handle the error if no item in the array meets the requirements f your func.
Any of both codes produce
console.log(findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; })))
8

function findElement(arr, func) {
var num;
arr.forEach(function(element) {
if (!num && func(element)) {
num = element;
}
});
return num;
}
For more options you can check this question: how to stop Javascript forEach?

As has already been mentioned, this is not how forEach should be used.
However, you can still get the behavior you want:
function findElement(arr, func) {
var num;
arr.forEach(item =>{
if (func(item)) {
num = item;
// .forEach does not have an early return
// but you can force it to skip elements by removing them
while (true) {
// Remove all elements
var removedItem = arr.shift();
if (removedItem === undefined) {
// All elements removed
break;
}
}
}
return num;
}
This is even mentioned in the documentation

maybe like this
function findElement(arr, func) {
var num = null;
for (var a = 0; a < arr.length && num === null; a++) {
var val = arr[a];
num = func(val) ? val : null;
}
return num;
}
console.log(findElement([1, 3, 5, 8, 9, 10], function(num) {
return num % 2 === 0;
}));

here is your findElement method with foreach
function findElement(arr, func) {
var num = 0;
arr.forEach(function(item){
if (func(item))
return item;
})
return num;
}

Related

How do you check for a type in an array?

I need to tell the program to search an array(that’s meant to be only numbers) if it contains any element that’s a string.
Also, the array is made up of the arguments to a function. Can someone please help? I’ve been trying to figure this out for at least an hour! This is what i did so far:
const sumAll = function(…args){
const newArray = Array.from(args)
for(let i = 0; i < newArray.length; i++){
if(newArray[i] === NaN){
return “ERROR”
}
}
}
You're looking for the function isNaN
const sumAll = function(...args){
const newArray = Array.from(args)
for(let i = 0; i < newArray.length; i++){
if(isNaN(newArray[i])){
return "ERROR"
}
}
}
console.log(sumAll(1,2,3)) // no output - undefined
console.log(sumAll(1,"two",3)) // error
let foundString = arrayWithPossiblyString.find(i=>isNaN(5-i));
Explanation:
5-"a" is a NaN.
isNaN function can be used to chec if something is NaN
You can use arguments keyword to access all the variables which would be passed as arguments to that specific function. Further you can use isNaN function to determine weather the given argument is a number or not.
function check(){
const arr = arguments
for(const item of arr) {
if(isNaN(item)){
return "Error"
}
}
}
check(1, "Hello", "4")
I suggest using the isNaN function:
...
if(isNaN(newArray[i])) {
return "ERROR";
}
You could check with Array#some and take isNaN as callback.
const sumAll = function(...args) {
if (args.some(isNaN)) return "ERROR";
}
console.log(sumAll(1, 2, 3)); // undefined
console.log(sumAll(1, "two", 3)); // ERROR
const sampleErrorArr = ['zero', 1, 2, 3, 4,]
const sampleArr = [1, 2, 3, 4, 5]
function sumAll(arr) {
let sum = 0
let hasNumber = true
arr.forEach((item, index) => {
if (typeof item === 'number') {
let temp = sum + item
sum = temp
}
else {
hasNumber = false
}
})
return hasNumber == true ? sum : "Error"
}
console.log(sumAll(sampleErrorArr)) //Error
console.log(sumAll(sampleArr)) // 15

how to make _.includes method

I am a junior developer who has been coding for 4 weeks.
I'm working on a JavaScript method.
I'll show you the code I used first.
_.each = function (collection, iteratee) {
if(Array.isArray(collection)===true){
for(let i=0;i<collection.length;i++){
iteratee(collection[i],i,collection)
}
}else{
let objvalues= Object.values(collection)
let objkeys = Object.keys(collection)
for(let i=0;i<objvalues.length;i++){
iteratee(objvalues[i],objkeys[i],collection)
}
}
};
_.includes = function (arr, target) {
let result
_.each(arr, function(a){
if(a === target)
result = true
if (a !== target)
result = false
})
return result;
};
It's a condition.
If the _.include method matches the value found by the element in the array, the true must be returned.
If the element in the array does not match the value you are looking for, you must return false.
I made the _include method.
If the element in the array does not match the value you are looking for, the return to false is successful.ten thousand
If the element in the array matches the value you are looking for, you must return true
This is where you fail.
It seems that the ture cannot be returned and only false is returned.
How should I handle this?
The problem is here:
_.each(arr, function(a){
if(a === target)
result = true
if (a !== target)
result = false
})
You reassign result on every iteration. As a result, the only iteration that matters for the final value of result is the last iteration.
Instead, initialize result to false, and reassign to true when the target is found:
const _ = {};
_.each = function(collection, iteratee) {
if (Array.isArray(collection) === true) {
for (let i = 0; i < collection.length; i++) {
iteratee(collection[i], i, collection)
}
} else {
let objvalues = Object.values(collection)
let objkeys = Object.keys(collection)
for (let i = 0; i < objvalues.length; i++) {
iteratee(objvalues[i], objkeys[i], collection)
}
}
};
_.includes = function(arr, target) {
let result = false;
_.each(arr, function(a) {
if (a === target)
result = true
})
return result;
};
console.log(
_.includes([1, 2, 3], 2)
);
It'd be cleaner to break the loop once a match is found, but your _each isn't set up for that:
const _ = {};
_.each = function(collection, iteratee) {
if (Array.isArray(collection) === true) {
for (let i = 0; i < collection.length; i++) {
iteratee(collection[i], i, collection)
}
} else {
let objvalues = Object.values(collection)
let objkeys = Object.keys(collection)
for (let i = 0; i < objvalues.length; i++) {
iteratee(objvalues[i], objkeys[i], collection)
}
}
};
_.includes = function(arr, target) {
for (const a of arr) {
if (a === target)
return true
}
return false;
};
console.log(
_.includes([1, 2, 3], 2)
);
In addition to what CertainPerfomance already said, you could see how Array.includes was implemented to get an inspiration, here is the specifications from TC39.

Create an Array recursively

I am trying to implement a recursive Function which returns an array of functions by filling it recursively
//arr = [1..1000]
//arr2 = [1,2,3]
function divideToSmallerTasks(arr, arr2) {
let arrLength = arr.length;
if (arr === undefined || arrLength == 0) {
return [];
} else if (arrLength > 100) {
return (getRelatedGames(arr.slice(0, 100), arr2)).push(divideToSmallerTasks(arr.slice(100, arrLength), arr2));
} else {
return (getRelatedGames(arr, arr2).push(divideToSmallerTasks([], arr2));
}
I expected to get back an array of functions smallerTasks = [function(arr[1..100],arr2[1,2,3]),function(arr[100,..200],arr2[1,2,3]),...] so I can run them in parallel later.
Your code is invoking the getRelatedGames function immediately as part of divideToSmallerTasks. What you want to do is create an anonymous function which, when executed, will run getRelatedGames as you stated, and return that. Something closer to the following: (untested)
function divideToSmallerTasks(arr,arr2){
let arrLength = arr.length;
if(arr === undefined || arrLength == 0){
return [];
}else if(arrLength > 100) {
let result = divideToSmallerTasks(arr.slice(100,arrLength),arr2);
result.push(function () { return getRelatedGames(arr,arr2); });
return result;
}else{
return [function () { return getRelatedGames(arr,arr2); }]
;}
This should result in a list of functions that you can execute one by one whenever you wish and perform the expected getRelatedGames call.
You need to return an array, instead of a new length, which is returned by push.
If you do not get a closure, you could add a function which calls getRelatedGames later. Here, this function is replaced with console.log.
function divideToSmallerTasks(arr, arr2) {
const defer = (fn, ...args) => () => fn(...args);
let arrLength = arr.length;
if (arr === undefined || !arrLength) {
return [];
}
if (arrLength > 3) {
return [defer(console.log, arr.slice(0, 3), arr2), ...divideToSmallerTasks(arr.slice(3, arrLength), arr2)];
}
return [defer(console.log, arr, arr2)];
}
var array = divideToSmallerTasks([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ['a', 'b', 'c']);
console.log(array);
array.forEach(fn => fn());
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to get all the array indexes that meet a condition in Javascript?

I would like to create a method that works like Array.prototype.findIndex but that returns all the indexes that match the condition:
Array.prototype.which = function(condition) {
let result = this.reduce((acc, x, i, arr) => {
if (condition) { acc.push(i) }
return acc
}, [])
return result
}
So that I could do:
[ 'a', null, 'b' ].which(x => x !== null) // [0, 2]
This doesn't work because I don't know how to link the x argument in the function call with the x value inside the which function.
You need to call the predicate:
Array.prototype.which = function(predicate) {
let result = this.reduce((acc, x, i, arr) => {
if (predicate(x)) { acc.push(i) }
return acc
}, [])
return result
}
I'd prefer Array#forEach.
Array.prototype.which = function(condition) {
let result = [];
this.forEach((v,i) => condition(v) ? result.push(i) : null);
return result;
}
console.log([1,2,3,4,5,6].which(v => v > 3));
An old-school for-loop method:
Array.prototype.which = function(test) {
const result = [];
for(let i = 0, l = this.length; i < l; i++) {
if (test(this[i])) {
result.push(i);
}
}
return result;
}
While it is easier to make a mistake with for and while, they sometimes offer performance gain because of fewer function calls.

is the value at this key an array?

I've written the following function to return the average of all the numbers of an array at a given key in an object:
var obj = {
key: [1, 2, 3]
};
function getAverageOfElementsAtProperty(obj, key) {
if (!(key in obj)) {
return 0;
} else if (obj[key].length === 0) {
return 0;
} else {
var total = 0;
for (i = 0; i < obj[key].length; i++) {
total += obj[key][i];
}
return total/(obj[key].length);
}
}
console.log(getAverageOfElementsAtProperty(obj, "key"));
Everything is fine, except I need to add one more else if statement before the else statement that checks if the value at that key is an array. If it isn't, it should return 0. I have looked up ways to do this but none of them have worked.
With instanceof:
var obj = {
k1: [1, 2, 3],
k2: null,
k3: "string",
k4: 5
};
function getAverageOfElementsAtProperty(obj, key) {
if (!(obj[key] instanceof Array) || obj[key].length == 0) {
return 0;
} else {
var total = 0;
for (i = 0; i < obj[key].length; i++) {
total += obj[key][i];
}
return total / (obj[key].length);
}
}
console.log(getAverageOfElementsAtProperty(obj, "k1"))
console.log(getAverageOfElementsAtProperty(obj, "k2"))
console.log(getAverageOfElementsAtProperty(obj, "k3"))
console.log(getAverageOfElementsAtProperty(obj, "k4"))
console.log(getAverageOfElementsAtProperty(obj, "k5"))
To check if a particular property is an array or not, use 'instanceof' operator.
In your case, add the below condition.
else if(! (obj.key instanceof Array)) {
return 0
}
When you say that you've looked up ways but they haven't worked, what have you tried and what problems did you find?
There is the Array.isArray function, which will return a boolean.
Array.isArray([]); // true
You can use Array.isArray(obj[key])
var obj = {
key: [1, 2, 3]
};
function getAverageOfElementsAtProperty(obj, key) {
if(!(key in obj)){
return 0;
}
if(!Array.isArray(obj[key])){
return 0;
}
if(obj[key].length === 0){
return 0;
}
return obj[key].reduce(function(op1, op2){
return op1 + op2;
}, 0)/obj[key].length
}

Categories