Callback function comprehension and return statement - javascript

Don't understand why I have to make the assignment on line 28 to make the code work! Lines 17 to 21 is where I get the results.This is a very basic solution - more interested in why the code works.
//Given a list of non-negative integers and a target sum, find a pair of numbers that sums to the target sum.
function findPairForSum(integers, target)
{
// your solution here
var integerPairArray = [];
// first have the first element as one of the pairs
var firstInteger = integers[0];
// will store the sum of integers
var sum = 0;
// iterate through the remaining elements
for(var index = 1; index < integers.length; index++)
{
// add each to the first element and compare the result with the target
sum = firstInteger + integers[index];
// if true then return the pair in an array
if(sum === target)
{
integerPairArray.push(firstInteger, integers[index]);
break;
}
// if the end of the array is reached and there is no result
if(index === integers.length - 1 && sum !== target)
{
// remove the first element from the array
integers.shift();
// repeat the loop
integerPairArray = findPairForSum(integers, target);
}
}
return integerPairArray;
}
// example
var pair = findPairForSum([3, 34, 4, 12, 5, 2], 17);
console.log(pair); // --> [12, 5]

Since the question has comments, and no answers, I will endeavor to provide an answer based on the comments made .#Solomon P Byer really helped me understand my code! Thank you!
The final return statement from the findPairForSum(integers, target) declaration will go to this function call/expression - var pair = findPairForSum([3, 34, 4, 12, 5, 2], 17); - made outside the function.
Because I made a recursive call within the findPairForSum(integers, target) function, the final return statement will initially go to the call within the function. And because it is a return statement, it has to be ‘caught’ as #Solomon P Byer mentioned.
It is caught by the integerPairArray variable and then the final return statement in the function returns the answer to the function call made outside the function and we get the answer! Whew!

Related

How to use break statement in an Array method such as filter?

I was trying to solve an algorithm challenge which required;
Drop the elements of an array (first argument), starting from the
front, until the predicate (second argument) returns true.
The second argument, func, is a function you'll use to test the first
elements of the array to decide if you should drop it or not.
Return the rest of the array, otherwise return an empty array.
Though I have been able to come up with a lengthy solution to this through looping the array I was wondering if there is a way to implement the break statement inside the methods.
Could it be accomplish by redefining the Array.prototype.filter method to accept a break statement ?
Though the solution could have been easy as such the methods of arrays in JavaScript doesn't accept this. How do you bypass that?
function dropElements(arr, func) {
return arr.filter(func);
}
You can just use for loop and when function returns true you can just break loop and return results from that index.
var arr = [1, 2, 3, 4, 5, 6, 7, 8];
function drop(data, func) {
var result = [];
for (var i = 0; i < data.length; i++) {
var check = func(data[i]);
if (check) {
result = data.slice(i);
break;
}
}
return result;
}
var result = drop(arr, e => e == 4)
console.log(result)
You can also use findIndex() and if match is found you can slice array from that index otherwise return empty array.
var arr = [1, 2, 3 ,4 ,5 ,6 ,7, 8];
var index = arr.findIndex(e => e == 4)
var result = index != -1 ? arr.slice(index) : []
console.log(result)

Is my solution recursive? (learning recursion)

I am practicing solving problems with recursion for a class.
I am solving the problems on this site : http://www.w3resource.com/javascript-exercises/javascript-recursion-functions-exercises.php
The question I am referring to is stated : Write a JavaScript program to get the integers in range (x, y).
Example : range(2, 9)
Expected Output : [3, 4, 5, 6, 7, 8]
Before looking at the solution I came up with this:
var range = function (start, end) {
var result = [];
var accumulator = start;
var accumulate = function () {
accumulator++;
if (accumulator === end) {
return;
} else {
result.push(accumulator);
}
accumulate();
};
accumulate();
return result;
};
The solution on the site is this:
var range = function(start_num, end_num)
{
if (end_num - start_num === 2)
{
return [start_num + 1];
}
else
{
var list = range(start_num, end_num - 1);
list.push(end_num - 1);
return list;
}
};
Is my solution technically still recursive? I had a similar answer on a quiz recently and I was told my solution is essentially iterative.
Though you use recursion, you have simply written a loop in the form of recursion.
I am going to answer this from the purely academical standpoint. If you want to avoid the intermediate state (result) and use purely functional constructs, I would write it like this
function range(start, end) {
function recRange(current, end) {
if (current > end)
return [];
return [current].concat(recRange(current + 1, end));
}
return recRange(start + 1, end - 1);
}
console.log(range(2, 9));
// [ 3, 4, 5, 6, 7, 8 ]
If you see here, we create a new function within the range function, which recursively creates a new array on every iteration (remember: this is not highly performant code, you can simply use loops and be done with this problem efficiently).
The base condition of the recursion is current < end. Once that is met, the recursion stops and an empty array is returned. In all the levels, a new array with the current value is concatenated with the result of the recursive call. So, the evaluation of the calls are roughly understood like this
[3].concat(recRange(3 + 1, end));
[3].concat([4].concat(recRange(4 + 1, end)));
...
at the end, when the recursion unwinds, the values will be like this
[3].concat([4].concat([5].concat([6].concat([7].concat([8].concat([]))))))
[3].concat([4].concat([5].concat([6].concat([7].concat([8])))))
[3].concat([4].concat([5].concat([6].concat([7, 8]))))
[3].concat([4].concat([5].concat([6, 7, 8])))
[3].concat([4].concat([5, 6, 7, 8]))
[3].concat([4, 5, 6, 7, 8])
[3, 4, 5, 6, 7, 8]
and that will be returned as the result.
To make your solution recursive, it should return some value and somehow combine the result of the recursive call to form the return value of the original call.
Let me illustrate that with an example, by modifying your solution:
var range = function (start, end) {
var accumulate = function (accumulator) {
if (accumulator === end - 1) {
return [accumulator]; // Stop condition
} else {
// Recursive block
var result = accumulate(accumulator+1); // recursive call
result.unshift(accumulator); // combine result
return result
}
};
return accumulate(start);
};
The modified accumulate function will return a one-element list for the stop condition, the simplest case it handles, where accumulator reaches the last value to return.
In the example range(2,9), the stop condition will return [8].
Then in the caller, the recursive block
var result = accumulate(accumulator+1);
result.unshift(accumulator);
return result
will take the list [8], and preprend the current value of accumulator (7), so it'll return [7,8].
...and the caller of accumulator(7), will receive [7,8] and preprend the value 6 to the list, to return [6,7,8].
At the end, the original call to accumulator(2) will generate the expected result [2,3,4,5,6,7,8].
Is my solution technically still recursive?
Yes. You're using tail recursion; however, since no arguments are being passed to accumulate() I can see why someone may say it's essentially iterative. You could easily replace your recursive call with a loop. Recursive algorithms typically leverage the stack.
Because of Javascript's closures, it is harder to understand the concept of recursion in Javascript compared to other languages like C++ or Java or C#.
To understand recursion, you must first understand recursion. :)

Function that takes an array of numbers and returns a new one w/ smallest # in index 0 and largest # in index 1

Working on exercises to build up my Javascript array skills.
Question is as follows: Write a function biggest_smallest that takes an array of numbers as an input, uses .forEach(), and returns an array containing the smallest number in the zeroth position and the largest number in the first position.
Instead of using forEach(), the only way I could think of doing this was as follows:
var array_of_nums = [7, 8, 120, 60, 10]
function biggest_smallest(array){
var new_array = []
for (var i = 0; i < array.length; i++){
if (array[i] === Math.min.apply(Math, array)){
new_array.unshift(array[i])
} else if (array[i] === Math.max.apply(Math, array)) { ? }
}
return new_array
}
I'm not able to figure out how to place the largest number in index 1 (let alone refactor it using a forEach() method) to solve this exercise complete. I am assuming my method of placing the smallest number in index 0 is correct.
Any help is much appreciated. Thanks.
Assuming this is supposed to work more or less like d3.extent I think the easiest option is just to iterate through with Math.min and Math.max checks:
function smallest_biggest(arr) {
// ditch if no input
if (!array.length) return [];
// start with comparable values
var extent = [Infinity, -Infinity];
arr.forEach(function(val) {
extent[0] = Math.min(extent[0], val);
extent[1] = Math.max(extent[1], val);
});
return extent;
}
Underscore's _.min and _.max functions used to skip the first check, with the incredibly annoying result that _.min([]) === Infinity.
edit My mistake, the question requires forEach iteration, so I suppose there is a need
There really is no need for iteration, you can just use Math.min/Math.max
function biggest_smallest(array){
return [Math.min.apply(null, array), Math.max.apply(null, array)];
}
I'd say first you need to find two variables: a (minimum value in the array) and b (the maximum). Then, outside the loop (that you can implement using foreach or the regular syntax) you just push the two values to the resulting array:
new_array.push(a);
new_array.push(b);
return new_array;
var array_of_nums = [7, 8, 120, 60, 10]
function smallest_biggest(arr) {
var new_array = []
arr.forEach(function() {
new_array[0] = Math.min.apply(Math, arr)
new_array[1] = Math.max.apply(Math, arr)
})
return new_array
}
smallest_biggest(array_of_nums)

How to populate an array with integers from a loop in javascript

I just signed up in codewars and I'm trying the first kata. This is the question:
Write a function to multiply a number (x) by a given number (y) a certain number of times (n). The results are to be returned in an array.
eg.
multiplyBy(2, 4, 6);
The output is: [8, 32, 128, 512, 2048, 8192]
I believe my code is write, when I do console.log I get the array that the exercise is asking for, but it won't let me proceed. I'd appreciate some help, thanks!
var array = [];
function multiplyBy(x, y, n) {
while (x<2049){
var z = x*y*n;
var x = z;
array.push(z)
}
}
multiplyBy(2,2,2);
console.log(array);
return array;
You have a few things going on outside your function which make it only work one time. Make sure that you keep everything inside the function until the last return
function multiplyBy(x, y, n) {
var array = []; // var this inside your function
for (; n > 0; --n) { // the loop is only supposed to happen n times
x = x * y; // you can reuse this variable (x)
array.push(x);
}
return array; // return statement should be inside your function
}
// example of logging the returned value
console.log(multiplyBy(2, 4, 6)); // [8, 32, 128, 512, 2048, 8192]
Your while loop also was hardcoded to x<2049, but this isn't always the case as it depends on the n parameter given to the function
it won't let me proceed
There are 3 issues in the code you posted that probably prevent you from proceeding,
The return array is probably throwing a syntax error because it's outside a function
In your code, calling multiplyBy several times appends the new values onto the end of the previous array
They are probably testing your function against other sets of values to check it works as expected, which is not true in your function, i.e. you gave the example inputs of 2, 4, 6 but used 2, 2, 2 in your own code
As a final note, try to get into the habbit of indenting your code, it'll save you headaches reading it later as it lets you quickly see where blocks begin and end
Your return is outside the function. And all calls to multiplyBy populate the same array. And your logic is flawed.
Probably, it should be
function multiplyBy(x, y, n) {
var array = [];
while (n--) array.push(x *= y)
return array;
}
console.log(multiplyBy(2,4,6));
Or, in ECMAScript 6,
var multiplyBy = (x, y, n) => Array(n).fill().map(a => x*=y);
ramove the return at the end, this must be used in function to return something, if not used the function will return undefined.
Look at this (single-line solution):
function multiplyBy(x,y,n) {
return Array.apply(null, new Array(n)).map(function(v, i) { return x * Math.pow(y, i + 1); });
}
DEMO

Why is the for loop not removing every odd number from the array (using the splice method)?

Problem
I am trying to remove all of the odd numbers from an array. For example, if I pass an array like so...
var arr = [1,2,3,6,22,98,45,23,22,12]
...the function removes all of the odd numbers except for 23. Why doesn't it remove 23 as well? If different numbers are used or if the order of the numbers is changed, it is always the last odd number that is not removed. I don't understand why though, since the for loop should continue until it gets to the end of the array (i < passedArray.length).
I am sure it is something simple, but I can't figure it out! Any help would be much appreciated ;)
Code
// PROBLEM: Loop through arr removing all values that aren't even.
// The original array
var arr = [1, 2, 3, 6, 22, 98, 45, 23, 22, 12];
// Function to remove all odd numbers from the array that is passed to it.
// Returns the new array.
var getEvenNumbers = function(passedArray) {
for (var i = 0; i < passedArray.length; i++) {
// If the remainder of the current number in the array is equal to one, the number is odd so remove it from the array.
if ((passedArray[i] % 2) === 1) {
arr.splice(i, 1);
}
}
// Return the array with only even numbers left.
return passedArray;
};
// Call the function and store the results.
var evenNumbers = getEvenNumbers(arr);
// Alert the new array that only has even numbers.
alert(evenNumbers);
The bug is that once you've spliced a number out of the array, you still increment i. This makes the code skip the number that follows the one that you've just deleted.
Since the number that precedes the 23 is odd (45), you never look at the 23.
You are chaging your array with splice, so your length changes as well. You could change your function to this:
var getEvenNumbers = function(passedArray) {
var evenArr=[];
for (var i = 0; i < passedArray.length; i++) {
if ((passedArray[i] % 2) != 1) { // if its even, add it
evenArr.push(passedArray[i]);
}
}
// Return the array with only even numbers left.
return evenArr;
};

Categories