Please explain how this function .reduce works [closed] - javascript

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.

Related

Why recursion behave differently in the two examples?

I have two examples of recursion, one calculate the sum of all elements of the array and the second return the count, both examples behave differently and i can't relate!
First Example:
const sum = (list) => {
if (list.length === 0) {
return 0;
}
return list[0] + sum(list.slice(1));
};
console.log(sum([1, 2, 3, 4])); // 10
The second:
const count = (list) => {
if (list.length === 0) {
return 0;
}
return 1 + count(list.slice(1));
};
console.log(count([0, 1, 2, 3, 4, 5])); // 6
Why the first recursion go through all array elements adding every element while the other added 1 to each element then returned just the final value?? i assumed it would do the same and the difference would be just adding 1 to the sum!!
The recursion is the same.
It visits all elements of the array and returns zero if no element is available.
For each element, it returns either the item for summing or one for counting.
Look at return 1 + count(list.slice(1)); in the count function. It would just ignore the 1st element in the list you pass recursively to the function and always use 1. Versus the sum function does consider that element. That effectively returns the count of times the function has been called which is 6
1st - sum, 2nd - count,
If you wish them to do the same thing you should use only one of them.

Basic Algorithm Scripting: Finders Keepers challenge

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

Find all ranges of consecutive numbers in array [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
Given a sorted array of numbers, how do you get ranges of consecutive numbers? The function should return ranges and single numbers as a string. Example:
function findRanges(arrayOfSortedNumbers) {
// logic here
}
findRanges([1, 3, 4, 5, 7]) => (expected output: "1, 3-5, 7")
findRanges([1, 2, 3, 5]) => (expected output: "1-3, 5")
findRanges([2, 3, 4, 5, 6]) => (expected output: "2-6")
Sorry for not being able to explain the problem better.
You can use Array.reduce() to do it:
Sort the array (safety)
Iterate over the array with reduce to create an object containing the ranges and the start of the active range (rangeStart).
On the first iteration, push the first element in the ranges and save this element as the rangeStart
On the successive iterations, if the value equals the last value + 1, we are in the same range, so we update it by changing the last value in the ranges array. Otherwise, we push the element in the ranges array and update rangeStart to be this element.
Return the ranges property of the object output by reduce and join it using commas.
function findRanges(numbers) {
return [...numbers].sort((a, b) => a - b).reduce((acc, x, i) => {
if (i === 0) {
acc.ranges.push(x);
acc.rangeStart = x;
} else {
if (x === acc.last + 1) {
acc.ranges[acc.ranges.length-1] = acc.rangeStart + '-' + x;
} else {
acc.ranges.push(x);
acc.rangeStart = x;
}
}
acc.last = x;
return acc;
}, { ranges: [] }).ranges.join(', ');
}
console.log(findRanges([1, 3, 4, 5, 7]));
console.log(findRanges([1, 2, 3, 5]));
console.log(findRanges([2, 3, 4, 5, 6]));

Fastest way to fill an array with multiple value in JS. Can I pass a some pattern or function to method fill insted of a single value in JS? [duplicate]

This question already has answers here:
Does JavaScript have a method like "range()" to generate a range within the supplied bounds?
(88 answers)
Closed 4 years ago.
Is it any way to create an array a selected size(for example 10) and immediately on the spot fill in it with some numbers specified pattern (1, 2, 3, OR 2, 4, 6 and so on) in one statement in JS?
let arr = new Array(10).fill( (a) => {a = 1; return a++; } );
console.log(arr); // Should be 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
In other words can I pass a some patern or function to method fill insted of a single value.
Actually there's much nicer idiom to create ranges: a spreaded Array constructor:
[...Array(n)]
creates an array of n undefined values. To get 0..n-1, just pick its keys:
[...Array(n).keys()]
for arbitrary ranges, feed it to map:
r = [...Array(10)].map((_, i) => i + 1)
console.log(r)
see here: Does JavaScript have a method like "range()" to generate an array based on supplied bounds?
old answer:
yep, you're looking for Array.from:
r = Array.from({length: 10}, (_, i) => i + 1);
console.log(r)
How does this work? .from inspects its first argument (which can be any object) and picks its .length property. Then, it iterates from 0 to length - 1 and invokes the second argument with two parameters - a value (which is undefined unless the first argument contains a corresponding numeric property) and an index, which takes values from 0...length-1. In this example, we have a function that just returns an index + 1, thus giving us 1..length.
Here's a useful wrapper for the above:
let range = (from, to) => Array.from({length: to - from + 1}, _ => from++);
console.log(range(1, 10))
For ES5, the idiom is Array.apply(null, {length:N}):
r = Array.apply(null, {length: 10}).map(function(_, i) {
return i + 1
})

JS: how to check array of integers for corresponding negative integer? [duplicate]

This question already has answers here:
Check if an element is present in an array [duplicate]
(9 answers)
Closed 5 years ago.
Given a (JS) array of integers, I am trying to ascertain if it is zer0-balanced -- that is, for any element x there is a corresponding element of -x - in a single line of code.
I would think you could do this using every() and includes() but can't quite get the right logic.
arr.every(n => arr.includes(-n)) obviously does not work because includes() is not a function, but that's the idea I've been failing least with. where to take this next? thank you!
If your environment has Array.every but not Array.includes, that's strange, but you can use Array.some instead of includes like so
arr.every(n => arr.some(x => x === -n))
You can use every with indexOf and a reduce statement to check if entire array actually sums up to zero as first pre-condition.
Using console.log, you can see it happen for every item in array in console.
If it does not find a matching negative element at any point, it stops execution there.
const arr = [1, 4, 8, -4, -8, -1,13,-13];
console.log((arr.reduce((x, y) => x + y) == 0) && arr.every(n => {console.log(n); return arr.indexOf(-n) > -1; }));
You could use a hash table and count with increment with positive numbers and decrement with negative numbers. If done, check all properties and return the nefgated check with Array#some.
function isBalanced(array) {
var hash = {};
array.forEach(a => hash[Math.abs(a)] = (hash[Math.abs(a)] || 0) + Math.sign(a));
return !Object.keys(hash).some(k => hash[k]);
}
console.log(isBalanced([1, 2, -2, -1]));
console.log(isBalanced([1, 2, -2, -1, -1, 1]));
console.log(isBalanced([1, 2, -2]));
console.log(isBalanced([1, 2, -2, 1, 1]));

Categories