how to get sum of odd, even using reduce method, i have done as show in below code but returning undefined , #js-beginner
//code below
nums= [1,2,3,4,5,6,7,8,9]
function getOddEvenSum(numbers){
let{even,odd} = numbers.reduce((acc, cuu) => cuu%2 === 0?acc.even + cuu:acc.odd+cuu,{even:0, odd:0})
return {even, odd}
}
console.log(getOddEvenSum(nums)
//output i am getting below
{even:undefined, odd:undefined}
The value that you return from your reduce callback will be the value of acc upon the next invocation/iteration of your array of numbers. Currently, your acc starts off as an object, but as you're only returning a number from your first iteration, all subsequent iterations will use a number as acc, which don't have .even or .odd properties. You could instead return a new object with updated even/odd properties so that acc remains as an object through all iterations:
const nums = [1,2,3,4,5,6,7,8,9];
function getOddEven(numbers){
return numbers.reduce((acc, cuu) => cuu % 2 === 0
? {odd: acc.odd, even: acc.even + cuu}
: {even: acc.even, odd: acc.odd+cuu},
{even:0, odd:0});
}
console.log(getOddEven(nums));
You can use Array.prototype.reduce like this:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const [odds, evens] = nums.reduce(
([odds, evens], cur) =>
cur % 2 === 0 ? [odds, evens + cur] : [odds + cur, evens],
[0, 0]
);
console.log(odds);
console.log(evens);
This is not how the syntax of reduce works. One possible implementation:
function getOddEven(nums) {
return nums.reduce(
({odd, even}, num) => num % 2 === 0 ?
{odd, even: even + num} :
{odd: odd + num, even},
{odd: 0, even: 0},
);
}
I would argue that this is not very clear. Since performance is probably not critical, a clearer alternative would be:
function getOddEven(nums) {
return {
odd: nums.filter(num => num % 2 == 1).reduce((acc, num) => acc + num),
even: nums.filter(num => num % 2 == 0).reduce((acc, num) => acc + num),
};
}
based on your code, you need to return acc
let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
function getOddEven(numbers) {
let {
even,
odd
} = numbers.reduce((acc, cuu) => {
if(cuu%2 == 0)
{
acc.even += cuu
}
else{
acc.odd += cuu
}
return acc
},
{
even: 0,
odd: 0
})
return {
even,
odd
}
}
console.log(getOddEven(nums))
Related
working with recursion and closures but not receiving the correct output.
The recursion block works correctly to take out elements and then add them to a total.
but when I try to implement the closure to the problem is doesn't work and the output is just the function instead of the correct output
let arr = [1, 2, 3, 4, 5];
function add(arr, total = 0) {
if (arr.length === 0) return total;
// console.log(total, 'total')
numberToAdd = arr[0];
// console.log(numberToAdd, 'number to be added to the total')
arr.shift();
// console.log(arr, 'array after taking out the first element', arr.length);
// console.log('total before recursion', total)
return num + add(arr, total + numberToAdd);
}
addTo15 = add(arr)
console.log(addTo15(100))
/** expected output: 115
*
* instead this outputs
*
* 100function(num) {
return num + add(arr, total + numberToAdd) ;
}
*/
Your question isn't quite clear to me, but my best guess is that you want to do something like this:
const addArrTo = ([n, ...ns]) => (num) =>
n == undefined
? num
: addArrTo (ns) (num + n)
const addTo15 = addArrTo ([1, 2, 3, 4, 5])
console .log (addTo15 (100))
which can also be written like this, if it's more familiar:
const addArrTo = (arr) => (num) =>
arr .length == 0
? num
: addArrTo (arr .slice (1)) (num + arr [0])
or even as
function addArrTo (arr) {
return function (num) {
return arr .length == 0
? num
: addArrTo (arr .slice (1)) (num + arr [0])
}
}
Each of these versions is a function that accepts an array of numbers and returns a function. The returned function takes a starting number, and then recursively calls itself, adding the current number from the input array to the running total.
I was working on this problem to create a function using a reduce method that will get the max number in an array.
The instructor's answer is:
const numbers = [1, 2, 3, 4, 4, 5, 1, 3, 4];
const max = getMax(numbers);
console.log(max);
function getMax(array) {
if (array.length === 0) return undefined;
return array.reduce((accumulator, current) => {
return (accumulator > current) ? accumulator : current
});
I tried something like this:
return array.reduce((accumulator, current) => {
if (accumulator < current)
console.log(accumulator, current);
return accumulator = current;
});
I added console.log (accumulator, current) because I wanted to see what's going on with my code. The log shows as follows:
console.log of my code
1 2
2 3
3 4
4 5
1 3
3 4
4
Question 1. I'd like to know why my function didn't give the right output (it returned 4, not the correct output 5). Shouldn't "accumulator" stay 5 when it is assigned as 5 during the loop?
Question 2. Why do I need to return (or add return in front of) array in the function, when there is already a return below the if statement?
You didn't use { ... } after your if statement, so only the first line console.log(...) is happening when the condition is met. The accumlator = current line always happens for each iteration. You must use return when using imperative style if statement. However you can skip return when using functional style expressions, ie (accumulator, current) => accumulator < current ? current : accumulator which says "if accumulator is less than current, return current, else return accumulator".
Consider this decomposed program. When we see max as an independent function, it helps us see precisely the type of function reduce is expecting -
const max = (a = 0, b = 0) =>
a < b // if a is less than b
? b // return b
: a // otherwise return a
const getMax = (numbers = []) =>
numbers.length === 0 // if numbers.length is zero
? undefined // return undefined
: numbers.reduce(max) // otherwise return reduction
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
We can see reduce is produces the following computation -
// given
[1, 2, 3, 4, 4, 5, 1, 3, 4]
// starting with the first two
r = max(1, 2)
// then the next number
r = max(r, 3)
// then the next number
r = max(r, 4)
// then the next number
r = max(r, 4)
Or without intermediate r = ... -
max(max(max(max(max(max(max(max(1, 2), 3), 4), 4), 5), 1), 3), 4)
We could write getMax without reduce, if we wanted -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const getMax = (numbers = []) =>
numbers.length === 0 // without any numbers,
? undefined // there can be no max.
: numbers.length === 1 // if we only have one,
? numbers[0] // we already know max.
: max(numbers[0], getMax(numbers.slice(1))) // else
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
Or maybe you haven't learned slice yet. You can use an array index, i, to step thru your array -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const getMax = (numbers = [], i = 0) =>
numbers.length === 0 // without any numbers,
? undefined // there can be no max.
: i + 1 >= numbers.length // if the next i is not in bounds,
? numbers[i] // this is the last number
: max(numbers[i], getMax(numbers, i + 1)) // else
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
Destructuring assignment can be used as well -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const getMax = ([ num, ...more ] = []) =>
more.length === 0
? num
: max(num, getMax(more))
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
This might show you how you can invent your own reduce -
const max = (a = 0, b = 0) =>
a < b
? b
: a
const reduce = (f, a = [], i = 0) =>
a.length === 0 // without any numbers,
? undefined // there can be no reduction.
: i + 1 >= a.length // if the next i is not in bounds,
? a[i] // this is the last element
: f(a[i], reduce(f, a, i + 1)) // else
const getMax = (numbers = []) =>
reduce(max, numbers) // <-- our reduce!
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5
console.log(getMax([]))
// undefined
console.log(getMax())
// undefined
Try use Math.max method:
const numbers = [1, 2, 3, 4, 4, 5, 1, 3, 4]
numbers.reduce((acc, rec) => Math.max(acc, rec))
//5
or
function max(numbers) {
return list.reduce((acc, rec) => acc > rec ? acc : rec)
}
if you need find max value without Math.max.
I'd like to combine identical elements in an array, into a single term with how many times the value appears
function combineArrayElements(arr) {
return arr.map((e, i, ar) => {
if (e === ar[i + 1] || (e[0] && e[0] === ar[i + 1])) {
return [e, e[1] + 1]
}
return e;
})
}
Some example input and output:
// input [3, 2, 2, 5, 1, 1, 7, 1]
// output [3,[2,2],5,[1,2],7,1]
// input [1, 1, 1, 2, 1]
// output [[1,3], 2, 1]
You could reduce the array and if the value is equal the last value, take an array and increment the counter.
const
getGrouped = array => array.reduce((r, v, i, { [i - 1]: last }) => {
if (v === last) {
if (!Array.isArray(r[r.length - 1])) r[r.length - 1] = [r[r.length - 1], 1];
r[r.length - 1][1]++;
} else {
r.push(v);
}
return r;
}, []);
console.log(getGrouped([3, 2, 2, 5, 1, 1, 1, 7, 1]));
console.log(getGrouped([2, 2, 2, 3]));
Thank, Joseph Cho - answer is:
function splitCounts(arr) {
let res = [];
let count = 1;
for (let i=0; i<arr.length; i++) {
if (arr[i] === arr[i+1]) {
count++;
} else {
res.push([arr[i], count]);
count = 1;
}
}
return res;
}
// [[3,1],[2,2],[5,1],[1,2],[7,1],[1,1]]
console.log(splitCounts([3,2,2,5,1,1,7,1]));
Refactored Nina Scholz's answer with longer variable names, comments, and slightly different control of flow:
const combineAdjacentElements = array => array.reduce((acc, val, i) => {
// if cur is different from prev value, add raw number
if (val !== array[i - 1]) {
acc.push(val)
return acc
}
// if first repetition, replace val with grouped array
if (typeof acc.at(-1) === 'number') {
acc[acc.length - 1] = [val, 2];
return acc
}
// if multiple repetition, increment counter in grouped array
acc.at(-1)[1]++;
return acc;
}, []);
const output = combineAdjacentElements([3, 2, 2, 2, 5, 1, 1, 7, 1])
console.log(JSON.stringify(output, null, 0))
// [3,[2,3],5,[1,2],7,1]
Further Reading
Check whether variable is number
How the get the last element in an array
How to replace the last index value in array javascript
Just use Array.reduce()
to get that.
I'm trying to solve this task of finding the unique element inside an array.
So far I managed to solve 95%, but I'm failing on 0. I get an error saying that expected 0 and got 1.
I should get //10, which it does, but after I'm failing the test online. For all other values it has passed.
Any ideas about how to solve this and what I'm missing here?
function findOne(arr) {
let x = arr[0];
for (let i of arr) {
if (i === x) {
continue;
} else {
x = i;
}
return x;
}
}
console.log(findOne([3, 10, 3, 3, 3]));
I don't really understand your code. You start with the first value in the array, then you loop through the array, skipping anything that's the same, and then return the first one that's not the same. That won't find unique values, it'll just find the first value that doesn't equal the first value. So for instance, try it on the array [1,2,2,2,2] and you'll get a result of 2 instead of 1, even though that's clearly wrong.
Instead, you can create a map of each value and its incidence, then filter by the ones that equal 1 at the end.
function findOne(arr) {
const incidences = arr.reduce((map, val) => {
map[val] = (map[val] || 0) + 1;
return map;
}, {});
const values = Object.keys(incidences);
for (let i = 0; i < values.length; ++i) {
if (incidences[values[i]] === 1) { return values[i]; }
}
return null;
}
EDIT The above won't preserve the type of the value (i.e. it'll convert it to a string always, even if it was originally a number). To preserve the type, you can use an actual Map instead of an object:
function findOne(arr) {
const incidences = arr.reduce((map, val) => {
map.set(val, (map.get(val) || 0) + 1);
return map;
}, new Map());
const singletons = Array.from(incidences).filter(entry => entry[1] === 1);
return singletons.map(singleton => singleton[0]);
}
Consider the following:
Recall that a span = max - min + 1;
Let Partition P1 be span from 0..span-1;
Let Partition P2 be span from span..(2*span)-1:
Place a number in P1 if it is not in P2.
Place a number in P2 if it is already in P1.
Once the number is in P2, do not consider it again.
If a number is in P1 then it is unique.
You can get all values that appear once, by using a map to count how many times each element has appeared. You can then reduce that map into an array of unique values:
const findUnique = arr => {
const mapEntries = [...arr.reduce((a, v) => a.set(v, (a.get(v) || 0) + 1), new Map()).entries()]
return mapEntries.reduce((a, v) => (v[1] === 1 && a.push(v[0]), a), [])
}
console.log(findUnique([3, 10, 3, 3, 3]))
console.log(findUnique([1, 2, 3, 2, 4]))
console.log(findUnique([4, 10, 4, 5, 3]))
If you don't care about multiple unique values, you can just sort the array and use logic, rather than checking every value, provided the array only contains 2 different values, and has a length greater than 2:
const findUnique = arr => {
a = arr.sort((a, b) => a - b)
if (arr.length < 3 || new Set(a).size === 1) return null
return a[0] === a[1] ? a[a.length-1] : a[0]
}
console.log(findUnique([3, 10, 3, 3, 3]))
console.log(findUnique([3, 3, 1]))
console.log(findUnique([3, 1]))
console.log(findUnique([3, 3, 3, 3, 3]))
Your code is complex, Try this
function findOne(arr) {
const uniqueItems = [];
arr.forEach(item => {
const sameItems = arr.filter(x => x === item);
if (sameItems.length === 1) {
uniqueItems.push(item);
}
});
return uniqueItems;
}
console.log(findOne([0, 1, 1, 3, 3, 3, 4]));
I'm getting all unique items from passed array, It may have multiple unique item
this is a way simpler and fast:
function findOne(arr) {
const a = arr.reduce((acc, e) => {
e in acc || (acc[e] = 0)
acc[e]++
return acc
}, {})
return Object.keys(a).filter(k => a[k] === 1)[0] || null
}
I have a number array [2, 1, 3, 4, 5, 1] and want to remove the smallest number in the list. But somehow my IF statement gets skipped.
I checked and by itself "numbers[i + 1]" and "numbers[i]" do work, but "numbers[i + 1] < numbers[i]" doesn't...
function removeSmallest(numbers) {
var smallestNumberKEY = 0;
for (i = 0; i <= numbers.lenths; i++) {
if (numbers[i + 1] < numbers[i]) {
smallestNumberKEY = i + 1;
}
}
numbers.splice(smallestNumberKEY, 1);
return numbers;
}
document.write(removeSmallest([2, 1, 3, 4, 5, 1]));
You have a typo in your code, array doesn't have lenths property
function removeSmallest(numbers) {
var smallestNumberKEY = 0;
for (var i = 0; i < numbers.length - 1; i++) {
if (numbers[i + 1] < numbers[i]) {
smallestNumberKEY = i + 1;
numbers.splice(smallestNumberKEY, 1);
}
}
return numbers;
}
document.write(removeSmallest([2, 1, 3, 4, 5, 1]));
But your algorithm wont work for another array, e.g [5, 3, 1, 4, 1], it will remove a value 3 too.
You can find the min value with Math.min function and then filter an array
function removeSmallest(arr) {
var min = Math.min(...arr);
return arr.filter(e => e != min);
}
You can use Array#filter instead
function removeSmallest(arr) {
var min = Math.min.apply(null, arr);
return arr.filter((e) => {return e != min});
}
console.log(removeSmallest([2, 1, 3, 4, 5, 1]))
Short one liner. If the smallest value exist multiple times it will only remove ONE. This may or may not be what you want.
const result = [6,1,3,1].sort().filter((_,i) => i) // result = [1,3,6]
It works by sorting and then creating a new array from the items where indeces are truthy(anything but 0)
another solution with splice and indexOf:
array = [2, 1, 3, 4, 5, 1];
function replace(arr){
arr = arr.slice(); //copy the array
arr.splice( arr.indexOf(Math.min.apply(null, arr)),1)
return arr;
}
document.write( replace(array) ,'<br> original array : ', array)
edit : making a copy of the array will avoid the original array from being modified
"Short" solution using Array.forEach and Array.splice methods:
function removeSmallest(numbers) {
var min = Math.min.apply(null, numbers);
numbers.forEach((v, k, arr) => v !== min || arr.splice(k,1));
return numbers;
}
console.log(removeSmallest([2, 1, 3, 4, 5, 1])); // [2, 3, 4, 5]
This is a proposal with a single loop of Array#reduce and without Math.min.
The algorithm sets in the first loop min with the value of the element and returns an empty array, because the actual element is the smallest value and the result set should not contain the smallest value.
The next loop can have
a value smaller than min, then assign a to min and return a copy of the original array until the previous element, because a new minimum is found and all other previous elements are greater than the actual value and belongs to the result array.
a value greater then min, then the actual value is pushed to the result set.
a value equal to min, then the vaue is skipped.
'use strict';
var removeSmallest = function () {
var min;
return function (r, a, i, aa) {
if (!i || a < min) {
min = a;
return aa.slice(0, i);
}
if (a > min) {
r.push(a);
}
return r;
}
}();
document.write('<pre>' + JSON.stringify([2, 1, 3, 2, 4, 5, 1].reduce(removeSmallest, []), 0, 4) + '</pre>');
I like this oneliner: list.filter(function(n) { return n != Math.min.apply( Math, list ) })
check it out here: https://jsfiddle.net/rz2n4rsd/1/
function remove_smallest(list) {
return list.filter(function(n) { return n != Math.min.apply( Math, list ) })
}
var list = [2, 1, 0, 4, 5, 1]
console.log(list) // [2, 1, 0, 4, 5, 1]
list = remove_smallest(list)
console.log(list) // [2, 1, 4, 5, 1]
list = remove_smallest(list)
console.log(list) // [2, 4, 5]
I had to do this but I needed a solution that did not mutate the input array numbers and ran in O(n) time. If that's what you're looking for, try this one:
const removeSmallest = (numbers) => {
const minValIndex = numbers.reduce((finalIndex, currentVal, currentIndex, array) => {
return array[currentIndex] <= array[finalIndex] ? currentIndex : finalIndex
}, 0)
return numbers.slice(0, minValIndex).concat(numbers.slice(minValIndex + 1))
}
function sumOfPaiars(ints){
var array = [];
var min = Math.min(...ints)
console.log(min)
for(var i=0;i<ints.length;i++){
if(ints[i]>min){
array.push(ints[i])
}
}
return array
}
If you only wish to remove a single instance of the smallest value (which was my use-case, not clear from the op).
arr.sort().shift()
Here is a piece of code that is work properly but is not accepted from codewars:
let numbers = [5, 3, 2, 1, 4];
numbers.sort(function numbers(a, b) {
return a - b;
});
const firstElement = numbers.shift();