multiplyOddByTwo function using javascript - javascript

I'm trying to get the odd numbers in the following array and then multiply by 2 using reduce method but it's giving me undefined error. Any help please.
const multiplyOddByTwo = (arr) => {
return arr.reduce((acc, curr) => {
if (curr % 2 === 0) {
arr.push(curr);
} else {
arr.push(curr * 2)
}
}, [])
}
console.log(multiplyOddByTwo([1, 2, 3]));

Two things to point out:
You have to make modifications to the second param in your reduce function. It is your initial value. The first param in the reduce callback(acc) is your cumulated value up till that particular iteration.
You have to return your cumulated value in each iteration. (When in the final iteration, this will be your calculated answer. Here you aren't returning anything hence the undefined)
const multiplyOddByTwo = (arr) => {
return arr.reduce((acc, curr) => {
if (curr % 2 === 0) {
acc.push(curr);
} else {
acc.push(curr * 2)
}
return acc;
}, [])
}
console.log(multiplyOddByTwo([1, 2, 3])); // [2,2,6]
This multiplies odd index elements by 2.
Edit: That is not undefined error. That is just undefined being returned. Any function not returning anything returns undefined.

If you would like it to only return odd numbers multiplied by 2 and not return the even then use this:
const multiplyOddByTwo = (arr) => {
const odd = arr.filter(num => num % 2 !== 0);
return odd.map(i => i * 2);
}
console.log(multiplyOddByTwo([1, 2, 3]));
Otherwise if you would like it to return all numbers but multiply odd numbers by 2 then use this:
const multiplyOddByTwo = (arr) => {
return arr.map(num => num % 2 === 0 ? num : num * 2);
}
console.log(multiplyOddByTwo([1, 2, 3]));

Related

JavaScript sum array using recursion

My task is to sum elements of an array and add it to second parameter (number) using recursion.
Return only gives me last value of sum. I would appreciate any feedback :)
const getArraySum = (numbersArray, initialValue) => {
// let sum = initialValue
// for (let i = 0; i < numbersArray.length; i++) {
// sum += numbersArray[i]
// } return sum
if (numbersArray.length === 0 ) {
return initialValue
} else {
let sum = 0
sum += numbersArray[numbersArray.length-1]
console.log (numbersArray)
numbersArray.pop()
console.log (sum)
getArraySum (numbersArray)
return sum + initialValue
}
};
const result1 = getArraySum([4,7,10], 5)
console.log (result1)
You're ignoring the return value of the recursive call to getArraySum. Instead, you should add it to the returned value:
const getArraySum = (numbersArray, initialValue) => {
if (numbersArray.length === 0) {
return initialValue
}
return numbersArray.pop() + getArraySum(numbersArray, initialValue);
};
const result = getArraySum([4,7,10], 5)
console.log (result)
Note that the initialValue should only be taken into consideration once, in the end condition where the array is empty.
The idea is to split an array into head (=the first element or null for an empty array) and tail (everything else). Then, establish that the sum is head + sum(tail):
let sum = ([head = null, ...tail]) =>
head === null ? 0 : head + sum(tail)
console.log(sum([1,2,3,4]))
Having an initial value is a silly requirement, but it goes the same way:
let sum = ([head = null, ...tail], init = 0) =>
init + (head === null ? 0 : head + sum(tail))
console.log(sum([1, 2, 3, 4], 100))
You could take the single values a summing variable and return immediately if the array is empty.
Otherwise return the function call with a new shorter array and hte sum of sum and the first element.
const
getSum = (numbers, sum = 0) => {
if (!numbers.length) return sum;
return getSum(numbers.slice(1), sum + numbers[0]);
};
console.log (getSum([4, 7, 10], 5));
As long as the array has an element, return last element (pop) plus getArraySum([rest of the array]), otherwise return initial value:
const getArraySum = (numbersArray, initialValue) => {
if (numbersArray.length === 0 ) {
return initialValue
} else {
return numbersArray.pop() + getArraySum(numbersArray, initialValue);
}
};
const result1 = getArraySum([4,7,10], 5)
console.log (result1)

Calculating second largest number in array (Javascript) : Seems to work in Sandbox but fails Hackerrank testing

Tried to determine the second largest number in an array (Javascript) on CodeSandbox. It seems to work fine, but it fails the CodeWars testing. I have added a dummy array just to run my own tests in Sandbox.(Have mercy, I'm a beginner and this is my first StackOverFlow question)
const nums = [3, 100.3, 88, 1, -2.4, 9, 18];
const getSecondLargest = (nums) => {
const descending = nums.sort((a, b) => b - a);
return descending[1];
};
console.log(getSecondLargest(nums)); // console returns 88
EDIT: Okay so I with my super-tired brain I said CodeWars, when I actually meant Hackerrank (so sorry!). I realized they didn't necessarily test with NaNs, but they did have repeating numbers, so using the index of [1] isn't ideal. The exercise is from the 10 Days of Javascript - Day 3: Arrays https://hackerrank.com/domains/tutorials/10-days-of-javascript
So I now tried this code below, and it passes...but my code seems a bit janky, is there a cleaner way to write this, and can I combine it with the isNan logic then?
const nums = [3, 100, 88, 100, -2.4, 9, 18];
const getSecondLargest = (nums) => {
const ascending = nums.sort((a, b) => a - b);
if (ascending[ascending.length - 2] === ascending[ascending.length - 1]) {
return ascending[ascending.length - 3];
} else {
return ascending[ascending.length - 2];
}
};
console.log(getSecondLargest(nums)); // console returns 88
It looks like there maybe strings in the array and you need to handle that. Here are a few ways:
One is to filter the non-numerical stuff out before sorting. You can use isNaN() to test if an object "is not a number".
const getSecondLargest = (nums) => {
const descending = nums
.filter(n => !isNaN(n))
.sort((a, b) => b - a);
return descending.length < 2 ? undefined : descending[1];
};
Another option is to handle the strings in sorting. Push them to the end of the array:
const getSecondLargest = (nums) => {
const descending = nums.sort((a, b) => {
if (isNaN(a) && isNaN(b)) return 0;
if (isNaN(a)) return 1;
if (isNaN(b)) return -1;
return b - a;
});
return descending.length < 2 || isNaN(descending[1]) ? undefined : descending[1];
};
A third way is a simple for loop that keeps track of the 2 highest values:
const getSecondLargest = (nums) => {
let max1 = undefined;
let max2 = undefined;
for (let n of nums) {
if (isNaN(n)) continue;
if (max2 === undefined || n > max2) {
if (max1 === undefined || n > max1 ) {
max2 = max1;
max1 = n;
}
else {
max2 = n;
}
}
}
return max2;
}

Recursively square each number in an array [duplicate]

This question already has answers here:
Javascript recursive array flattening
(27 answers)
Closed 1 year ago.
I came up with the following solution for returning an array of squared numbers, sorted in ascending order.
function sortedSquaredArray(array) {
let squaredArray = [];
for(i=0;i<array.length;i++){
squaredArray.push(array[i] ** 2);
}
return squaredArray.sort((a,b) => a-b);
}
I'm trying to get better at writing recursions, so I'm attempting to turn the above into a pure recursive function (with no inner function).
This is my attempt.
function sortedSquaredArray(array) {
let squaredArray = [];
squaredArray.push(array[0] ** 2);
if(array.length) sortedSquaredArray(array.shift());
return squaredArray.sort((a,b) => a-b);
}
I believe its the sortedSquaredArray(array.shift()) that's causing this to fail.. I thought about using .slice and .concat somehow, but struggling to wrap my head around it.
What am I missing?
.shift returns the removed element - it doesn't return the array after being mutated.
For proper recursion, you also either need to pass along the array as a parameter, or create it during the final iteration and return it back for the prior callers to insert their items into.
So that you only sort at the end, I'd recommend passing it as a parameter, so that the final call with no recursion can sort.
function sortedSquaredArray(input, squares = []) {
if (!input.length) {
return squares.sort((a, b) => a - b);
}
squares.push(input.pop() ** 2);
return sortedSquaredArray(input, squares);
}
function sortedSquaredArray(input, squares = []) {
if (!input.length) {
return squares.sort((a, b) => a - b);
}
squares.push(input.pop() ** 2);
return sortedSquaredArray(input, squares);
}
console.log(sortedSquaredArray([2, 4, 1]));
A similar option that doesn't mutate the parameter:
function sortedSquaredArray(input, squares = []) {
if (!input.length) {
return squares.sort((a, b) => a - b);
}
const [firstItem, ...rest] = input;
squares.push(firstItem ** 2);
return sortedSquaredArray(rest, squares);
}
or
function sortedSquaredArray(input, squares = []) {
if (!input.length) {
return squares.sort((a, b) => a - b);
}
squares.push(input[0] ** 2);
return sortedSquaredArray(input.slice(1), squares);
}
If you want just one parameter, then do the other approach I mentioned - create the array during the final iteration and return it back up:
const recurse = (input) => {
if (!input.length) {
return [];
}
const square = input.pop() ** 2;
return sortedSquaredArray(input).concat(square);
};
function sortedSquaredArray(input) {
return recurse(input).sort((a, b) => a - b);
}
console.log(sortedSquaredArray([2, 4, 1]));
I would separate the sorting from the squaring, since the squaring might be useful on its own. This is a useful way to do this sort of recursion for smallish problems:
const squaredArray = ([n, ...ns]) =>
n == undefined
? []
: [n * n, ... squaredArray (ns)]
const sortedSquaredArray = (ns) =>
squaredArray (ns) .sort ((a, b) => a - b)
console .log (sortedSquaredArray ([4, 9, 2, 5, 8]))

how can I do this better in javascript: add a pair (key, value) to a hash while iterating?

I wrote this solution that works, although I would like to verify with the community if there is a better way to add a pair (key, value) to a hash while I am iterating. I have to create a new function with name addPairToHashAndReturnIt as an auxiliar function.
The challenge is the following:
Create a function countBy that accepts an array and a callback, and returns an object. countBy will iterate through the array and perform the callback on each element. Each return value from the callback will be saved as a key on the object. The value associated with each key will be the number of times that particular return value was returned.
function countBy(array, callback) {
return array.reduce(
(acc, each) =>
(!acc[callback(each)] && addPairToHashAndReturnIt(acc, callback(each), each)) ||
((acc[callback(each)] += 1) && acc),
{}
);
}
const addPairToHashAndReturnIt = (hash, key, value) => {
hash[key] = 1;
return hash;
};
function evenOrOddNumber(num) {
if (num % 2 === 0) return 'even';
else return 'odd';
};
console.log(
countBy([1, 2, 3, 4, 5], evenOrOddNumber)
); // should log: { odd: 3, even: 2 }
So, what do you think about this solution?
Simplify your logic, don't make it unnecessarily complicated.
We aren't wanting to overwrite the value of hash[value] with 5 (for instance), we're just wanting to increment hash[value] every time we get a match. The form will look like hash[value]++, not hash[value] = item.
See also: Is Reduce() Bad?
const evenOrOddNumber = (num) => (num % 2 == 0)
? 'even'
: 'odd';
const countBy = (array, callback) => {
// store counts
const counts = {};
array.forEach(item => {
// store callback result, previous count
const val = callback(item);
const prevCount = counts[val] || 0;
// increment count
counts[val] = prevCount + 1;
});
return counts;
}
console.log(
countBy([1, 2, 3, 4, 5], evenOrOddNumber)
); // should log: { odd: 3, even: 2 }

Javascript - Counting array elements by reduce method until specific value occurs doesn't give a correct output

const arr = [5,6,0,7,8];
const sum = (arr,num) => arr.reduce((total)=>(num==0 ? total : total+num), 0)
console.log(sum(arr, 0))
Please check how can I make it work. Did some mistake but don't know what exactly. Output is a function instead of a result.
This is awkward to do in .reduce because it goes through the entire array. If we do a naive implementation you can see the problem:
const arr = [5,6,0,7,8];
const sum = (arr,num) => arr.reduce((total, x)=>(num==x ? total : total+x), 0)
console.log(sum(arr, 0))
We now make the check correctly - num==x will return true when x is zero (the value of num). However, the result is wrong because this only returns true once but any other iteration it's still true. And here is the same thing with more logging that describes each step of the process:
const arr = [5,6,0,7,8];
const sum = (arr,num) => arr.reduce((total, x)=> {
const boolCheck = num==x;
const result = boolCheck ? total : total+x;
console.log(
`total: ${total}
num: ${num}
x: ${x}
boolCheck: ${boolCheck}
result: ${result}`);
return result;
}, 0)
console.log(sum(arr, 0))
So, you need to add some flag that persists between iterations, so it doesn't get lost.
One option is to have an external flag that you change within the reduce callback:
const arr = [5,6,0,7,8];
const sum = (arr,num) => {
let finished = false;
return arr.reduce((total, x) => {
if(x === num)
finished = true;
return finished ? total : total+x;
}, 0)
}
console.log(sum(arr, 0))
Alternatively, you can have that flag internal to the reduce callback and pass it around between calls. It works the same way in the end but makes the callback function pure. At the cost of some unorthodox construct:
const arr = [5,6,0,7,8];
const sum = (arr,num) => {
return arr.reduce(({total, finished}, x) => {
if(x === num)
finished = true;
total = finished ? total : total+x;
return {total, finished};
}, {total: 0, finished: false})
.total
}
console.log(sum(arr, 0))
If you want to use reduce but you're OK with using other methods, then you can use Array#indexOf to find the first instance of a value and Array#slice the array that contains any value up to the target value:
const arr = [5,6,0,7,8];
const sum = (arr,num) => {
const endIndex = arr.indexOf(num);
return arr.slice(0, endIndex)
.reduce((total, x)=> total+x, 0)
}
console.log(sum(arr, 0))
Or in as one chained expression:
const arr = [5,6,0,7,8];
const sum = (arr,num) => arr
.slice(0, arr.indexOf(num))
.reduce((total, x)=> total+x, 0);
console.log(sum(arr, 0))
Other libraries may have a takeUntil or takeWhile operation which is even closer to what you want - it gets you an array from the beginning up to a given value or condition. You can then reduce the result of that.
Here is an example of this using Lodash#takeWhile
By using chaining here, Lodash will do lazy evaluation, so it will only go through the array once, instead of scanning once to find the end index and going through the array again to sum it.
const arr = [5,6,0,7,8];
const sum = (arr,num) => _(arr)
.takeWhile(x => x !== num)
.reduce((total, x)=>total+x, 0)
console.log(sum(arr, 0))
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
As a note, if you are using Lodash, then you may as well use _.sum(). I didn't above just to illustrate how a generic takeUntil/takeWhile looks.
const arr = [5, 6, 0, 7, 8];
const sum = (arr, num) => _(arr)
.takeWhile(x => x !== num)
.sum()
console.log(sum(arr, 0))
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
Since you need to stop summing values part way through the array, this might be most simply implemented using a for loop:
const arr = [5, 6, 0, 7, 8];
const num = 0;
let sum = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] == num) break;
sum += arr[i];
}
console.log(sum);
If you want to use reduce, you need to keep a flag that says whether you have seen the num value so you can stop adding values from the array:
const arr = [5, 6, 0, 7, 8];
const sum = (arr, num) => {
let seen = false;
return arr.reduce((c, v) => {
if (seen || v == num) {
seen = true;
return c;
}
return c + v;
}, 0);
}
console.log(sum(arr, 0));
console.log(sum(arr, 8));
call it as follows:
console.log(sum(arr, 0)());
You need parenthesis to execute the function ()
sum(arr, 0)
Without parenthesis you store a reference to the function in the variable

Categories