Basic Algorithm Scripting: Finders Keepers challenge - javascript

Could someone please tell me why FCC is not accepting my solution, even though it passes all the tests?
Below is the link to the challenge, but I will post the question and tests here to comply better with the community.
FCC Chalenge:
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/finders-keepers
Basic Algorithm Scripting: Finders Keepers
Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument). If no element passes the test, return undefined.
findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }) should return 8.
findElement([1, 3, 5, 9], function(num) { return num % 2 === 0; }) should return undefined.
I have returned the solution as per below:
function findElement(arr, func) {
"use strict"
return arr.filter(num => func(num)).toString('').substring(1,0);
}
console.log(findElement([1, 3, 5, 8, 9, 10], num => num % 2 === 0));
// It returns 8 as expected...
The outcome of console.log(findElement([1, 3, 5, 8, 9, 10], num => num % 2 === 0)); is 8 as expected, but for some reason it does no pass the test.
I would like to know if I am doing something wrong.
Thanks

You have a few issues. Currently, you're returning a portion of a string (which may not include your entire result), when really you should be returning the entire value of the first element which matches your predicate (ie: the function passed through). This means that you're returning a string rather than a number, which already is incorrect. Also, you are not returning undefined when the passed-through function doesn't match any values.
Instead, consider changing your code so that it either grabs the first element from the array returned by .filter() (by targeting index [0]) or by using the .find() method (which will stop looping once it has found it's value) like so:
function findElement(arr, func) {
"use strict"
return arr.find(func); // non point-free version: arr.find(n => func(n))
}
console.log(findElement([1, 3, 5, 8, 9, 10], num => num % 2 === 0)); // 8
console.log(findElement([1, 50], num => num % 2 === 0)); // 50
console.log(findElement([1, 1], num => num % 2 === 0)); // undefined

Another possible solution.
const findElement = (arr, func) => arr[arr.map(func).indexOf(true)];

Related

filter and includes in array, how does that work?

I'm trying to understand how filter() and includes() work with arrays in javascript but english isn't my native language so I would really appreciate it if someone could explain the example below to me like I was 5:
const removeFromArray = function(...num) {
let array = num[0];
return array.filter(val => !num.includes(val))
};
This function takes an array and some other arguments then removes the other arguments from that array for example removeFromArray([1, 2, 3, 4], 3) should remove 3 and return [1,2,4]
How does this part work?
return array.filter(val => !num.includes(val))
Why the exclamation mark and also how do those two methods work together?
I think the key to understanding what is going on is the parameter(s) of the function, num. The code uses a nice trick that I have not encountered before. So, num is:
[[1, 2, 3, 4], 3];
a 1D array with TWO elements: [1, 2, 3, 4] at index 0, and 3 at index 1. As a result:
num.includes([1, 2, 3, 4]) // is true
num.includes(3) // is true
num.includes(anything-else) // is false
The
Array#includes
method determines whether an array includes a certain value among its
entries, returning true or false as appropriate.
In the simplest form, whenever a boolean expression is prefixed with !, the result of the expression is negated. For example:
!num.includes(3) // becomes false
The
Array#filter
method creates a new array with all elements that pass the test
implemented by the provided function.
Pass the test simply means return true.
Now we are ready to look at num[0].filter(val => !num.includes(val)). Or:
[1, 2, 3, 4].filter(val => !num.includes(val))
Please recall that ONLY 3 and [1, 2, 3, 4] return true to:
num.includes(val)
Hence of all the elements of num[0] or [1, 2, 3, 4] only 3 returns false to the negated expression:
!num.includes(val)
1, 2, and 4 return true or !false, meaning that they pass the test and hence will be returned by the function:
[1, 2, 4];
Please note that val => !num.includes(val) is a shorthand way of writing:
function( val ) {
return !num.includes(val);
}
const removeFromArray = function(...num) {
let array = num[0];
return array.filter(val => !num.includes(val))
};
console.log( removeFromArray([1, 2, 3, 4], 3) );
Rest parameters shouldn't be used like that, it should only be used for like values. So, the array should be accepted separately and only the numbers to remove should be accepted using rest (refer to the snippet below).
The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.
So, we simply filter out numbers that are not present in the itemsToRemove array.
const removeFromArray = (array, ...itemsToRemove) =>
array.filter((item) => !itemsToRemove.includes(item));
removeFromArray([1, 2, 3, 4], 3, 2);
! means "not". If something is falsy (null, 0, false, an empty string), then !something returns true. This leads to a really strange looking "cheat code" where you can convert any value to a boolean (i.e. truthy to true and falsy to false) via !!value. One exclamation point converts it to a boolean value that's true if value is falsy, then the second exclamation point changes true to false (or false to true)!
array.prototype.filter requires a function to be evaluated against each element and returns an array of only the elements where the supplied function returns a truthy value.
It might be easier to think of the following code that is nearly equivalent to yours...
const removeFromArray = function(array, ...valsToRemove) {
const isValToKeep = val => array.includes(val) === false;
return array.filter(isValToKeep)
};
The only difference in this code, besides being longer, is that the first argument won't be looked for within the first argument. Consider
const a1 = [1,2,3];
a1.push(a1); // appends itself as its last element
In your version, removeFromArray(a1, 2) would return [1, 3], but mine doesn't combine the first argument as one of the elements to look for and remove from the first argument, which is probably what most people would expect and be more performant, but would definitely have a different effect in the example returning [1, 3, a1], i.e. [1, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [...]]]]]]]]
This is a simple form to explain how to use filter
function isBigEnough(value) {
return value >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// result is [12, 130, 44]
This example is from: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Lets start by rewriting this line:
Before
return array.filter(val => !num.includes(val))
after
const callback = val => {
return !num.includes(val)
}
const filteredArray = array.filter(callback);
return filteredArray
Now lets break and explain parts of this statement:
! num.includes(val)
includes method here will check if num has val in it. If num has val it will return true else it will return false. note the ! at the begining of the line ,that will change the value returned by includes to its opposite e.g if value returned is false it will change it to true if value returned is true it will change it to false.
array.filter(callback)
The filter method here will go through every element of the array and at each element it will ask whether to add that element to the filteredArray or not based on what is returned from the callback. If callback returns true(truthy) it will add it else it will not add it. The callback should only return true(truthy) or false(falsy).
example :
At index 0 of array the filter will ask did callback return true if it returned true the element at index 0 will be added to the filtered array. It will do the same for the rest of the elements.
How they work together:
array has [1,2,3,4] so array.filter(callback) will go over each element and call callback on each. Based on your function num has this [[1,2,3,4],3] so when val from array is 3 !num.includes(val) will return true but this ! will change it to false as a result callback will return false and 3 will not be included in the final array the filteredArray.
Hope a 5 year old can understand this explantion. You can now rewrite your function like this :
const removeFromArray = (array, ...numbersToRemove) => array.filter((number) => !numsToRemove.includes(number));

JS - How is .filter working with this callback?

I'm new to Javascript and am currently going through the basics of callback functions and am having difficulty understanding why the code below returns an array of odds:
Code:
let numbers = [1, 2, 4, 7, 3, 5, 6];
function isOddNumber(number) {
return number % 2;
}
const oddNumbers = numbers.filter(isOddNumber);
console.log(oddNumbers); // [ 1, 7, 3, 5 ]
I see that the .filter is calling isOddNumber but I'm not sure how isOddNumber is passing or failing the values in the array. Is the return number % 2 pushing a 1 or 0 back to .filter and interpreting as truthy or falsy?
Any help here would be greatly appreciated!
#pilchard:
filter() passes each element to the provided isOddNumber callback, which in turn returns the remainder after dividing by 2 (either 0 or 1), which is evaluated as a boolean by the filter.

How to write a function which takes n number of arguments and gets called n number of times

I was asked the below question where one function takes n number of arguments and gets called n times. I could not get answers anywhere. Please help me with below code
test(1, 2, 3, 4,5 ....n)(1, 2, 3, 4, 5, ....n)(1, 2, 3, 4, 5, ....n)........
Thanks in advance
Is this the only detail, you were given? You can use rest operator to get dynamic parameters, It could be any number and its has the results in the form of array. SO you can read the length property to run the loop.
If you can provide more details, the solution can be improved.
const a = (...arg) => {
console.log(arg);
if (arg.length === 0) return `No Args`;
arg.forEach((el, index, arr) => {
// do things here
})
}
a(1, 2, 4, 5)
console.log(a())
Or what I can see from the question you can use cascaded(closure )function like this:
const mul = a => b => c => a*b*c;
console.log(mul(1)(2)(3));
You can also return the function body itself and call it n times.
const funcCall = (...params) => {
console.log(params);
return funcCall
}
funcCall(1, 2, 3)(4, 5, 6)(7, 8, 9);
I think what you are looking for is rest syntax. You can read more about it here Following is an example of rest syntax -
function test(...args) {
console.log(args);//array
for (let element of args) {
//do something
}
}
test(1, 2, 3, 4, 5, 6);

Please explain how this function .reduce works [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
function countInArray(array, value) {
return array.reduce((n, x) => n + (x === value), 0);
}
console.log(countInArray([1, 2, 3, 4, 4, 4, 3], 4)); // 3
I was watching for explanation in manuals, but it seems to me very complex to understand.
So I get that 0 is the starting total, and that x===1 should be equal to 1 or 0 depending on the truth.
I'm mainly confused with n because I read that n is the return value of the previous function, but there's no previous function in the beginning.
but there's no previous function in the beginning.
Exactly - The "previous function" doesn't exist at the start - so n starts off as 0, the second argument you passed to reduce. The docs give you the argument list:
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
The last argument there is initialValue, which is exactly what it sounds like - it is the inital value of accumulator.
function countInArray(array, value) {
return array.reduce((n, x) => n + (x === value), 0);
}
console.log(countInArray([1, 2, 3, 4, 4, 4, 3], 4)); // 3
the above countInArray function look up the no of instances of given value in given array.
in JS true is equal to 1 therfore 0 + 1 is 2 and so on.
countInArray([1, 2, 3, 4, 4, 4, 3], 4) here you are trying to count the no of inctance of 4 the answer is 3.
function countInArray(array, value) {
return array.reduce((n, x) => n + (x === value), 0);
}
console.log(countInArray([1, 2, 3, 4, 4, 4, 3], 4)); // 3
Lets break it into parts:
The function countInArray intends to count occurrences of the value (not necessarily a number) in a given array. Therefore accepts an array and a value.
The reduce function works on the given array. it gets 2 params: a function and a initialization value for the accumulator.
the function also get 2 params: an accumulator (n in this case) and a current value (x in this case). They are both accessible in every iteration, but the accumulator's keeps its value between iterations while the current value varies at each itaration (possess a new array value).
In every iteration we ask if the current array value equals the value we entered in step 1, if so, we increase by 1 the accumulator (which was initialized to 0 ).
*. The line n + (x === value) can be a little confusing. notice that in javascript 1 + true equals 2 and 1 + false stays 1.

why does every not work inside an if statement when I am checking for equality?

I am trying to find the common number in two arrays using every. As expected, every does not work when I check for equality inside of my if statement. However, it does work in my second example. Unfortunately, I do not understand why. Can someone explain why the second example works where the first does not?
// Will not work here
function findCommonNumbersInArrays(arOne, arTwo) {
var cm = [];
for (var i = 0; i <= arOne.length; i++) {
if (arTwo.every(a => a === arOne[i])) {
cm.push(arOne[i]);
}
}
return cm;
}
console.log('These are the common numbers: ' + findCommonNumbersInArrays([1, 2, 3, 4, 5], [3, 4, 6, 7, 8]));
// Works here
function common(arOne, arTwo) {
var cm = [];
for (var i = 0; i <= arOne.length; i++) {
if (!arTwo.every(a => a !== arOne[i])) {
cm.push(arOne[i]);
}
}
return cm;
}
console.log('These are the common numbers :' + common([1, 2, 3, 4, 5], [3, 4, 6, 7, 8]));
The non-working version:
arTwo.every(a => a === arOne[i])
In English:
Every item in arTwo is equal to the current item in arOne.
That will obviously never be true if there are at least two different items in arTwo, since two different items cannot be equal to one other item.
The working version:
!arTwo.every(a => a !== arOne[i])
In English:
Not every item in arTwo does not match the current item in arOne.
Since double negatives are super confusing, let's rephrase:
Not every item in arTwo is different from the current item in arOne.
Rephrase:
Some items in arTwo are the same as the current item in arOne.
That should explain the difference.
Which means, the some method would actually be much more appropriate:
arTwo.some(a => a === arOne[i])

Categories