How to totalize positive and negative numbers - javascript

Can anyone help me how to totalize/Collect positive and negative numbers in javascript? What metodes shud I use

Some useful methods could be filter and reduce assuming you are referring to an array of numbers that you want to totalize [sic] (I assume you mean sum):
const nums = [5, 3, -2, 0, 9, -8, 7]
const positiveNumsTotal = nums.filter(num => num > 0).reduce((a, b) => a + b, 0)
const negativeNumsTotal = nums.filter(num => num < 0).reduce((a, b) => a + b, 0)
const overallTotal = nums.reduce((a, b) => a + b, 0)
console.log(`nums array: ${JSON.stringify(nums)}`)
console.log(`Postive number total: ${positiveNumsTotal}`)
console.log(`Negative numbers total: ${negativeNumsTotal}`)
console.log(`Overall total: ${overallTotal}`)

Related

When using using reduce with ternary inside a map, I seem to have troubles

this is to return an array of numbers that are the highest value of the arrays inside of the base array. I can get it to work when i use for statements. But I have tried to simplify it, and can't work out why it doesn't work. any help would be appriciated.
function largestOfFour(arr) {
return arr.map((x) => x.reduce((a, c) => c > a ? c : a, 0));
}
Example with input and output:
const input = [
[1,2,3,4,5],
[6,5,4,3,2,1],
[1,7,3,4,5,6],
];
function findHighestElements(arr) {
return arr.map((x) => x.reduce((a, c) => c > a ? c : a, 0));
}
console.log(findHighestElements(input)); // [5,6,7]
You don't need to reduce, you can do it by just Math.max. like this:
function findMaxNumbers(arr) {
return arr.map((x) => Math.max(...x));
}
let test = [[1, 2, 3],[4, 5, 6],[7, 8, 9]];
console.log(findMaxNumbers(test));
If you have values smaller than zero, you need to remove the start value
x.reduce((a, c) => c > a ? c : a, 0)
^
or use a very small start value, like -Number.MAX_VALUE.
To get the max of all the maxes, you can reduce the reductions. If you just want the max's, map the reduction.
const maxOfArray = a => a.reduce((a, c) => c > a ? c : a, -Number.MAX_SAFE_INTEGER); // thanks to Nina
const conciseVLAZMax = a => Math.max(...a); // thanks to VLAZ
let a = [
[1, 2, 3],
[6, -1, -2],
[3, 4, 5],
]
let maxs = a.map(maxOfArray);
let maxMax = maxOfArray(maxs);
console.log(maxs);
console.log(maxMax);

Sort an array of elements in ascending order by number of occurences

Having an array like this: [4, 2, 6, 1, 2, 5, 2, 4]
there are one occurences of 1, 5, 6
two occurences of 4
three occurences of 2
First, there must be added in ascending order the elements with one occurence: 1, 5, 6
After that, the elements with two occurences: 1, 5, 6, 4, 4
and the elements with three occurences: 1, 5, 6, 4, 4, 2, 2, 2
I've tried to sort the array and then to move the elements with more occurences to the end of the array but it's not very efficient.
Any ideas?
You could count frequencies using array Array.prototype.reduce method and then sort it by occurrence in ascending order.
let arr = [4, 2, 6, 1, 2, 5, 2, 4];
arr = Object.entries(
arr.reduce((prev, c) => {
const p = prev;
p[c] = p[c] ?? 0;
p[c] += 1;
return p;
}, {})
)
.sort((x, y) => x[1] - y[1])
.flatMap(([x, y]) => Array(y).fill(+x));
console.log(arr);
First you need to count the occurrences of each number in the array, we'll use a reduce for this like so:
let count = arr.reduce((acc, n) => {
acc[n] = (acc[n] || 0) + 1;
return acc;
}, {});
This will result in an object where the keys are the numbers and the values are their number of occurrences in the array arr.
Then we'll just sort the items by that count first then by the numbers themselves:
arr.sort((a, b) => (count[a] - count[b]) || (a - b));
(count[a] - count[b]) || (a - b) is using a short circuit evaluation, which results in a sort by count/number of occurrences in ascending order, then by the numbers themselves if count[a] - count[b] === 0 (meaning that the numbers a and b have the same count).
Demo:
let arr = [4, 2, 6, 1, 2, 5, 2, 4];
let count = arr.reduce((acc, n) => {
acc[n] = (acc[n] || 0) + 1;
return acc;
}, {});
arr.sort((a, b) => (count[a] - count[b]) || (a - b));
console.log("[ " + arr.join(", ") + " ]");

Strange behaviour of reduce method in JavaScript?

I was trying to create an even number array of Fibonacci series using Functional Programming - below code
let a = [1, 2];
const r = (n) =>
Array.from(
a[a.length - 1] + a[a.length - 2] <= n ?
a.push(a[a.length - 1] + a[a.length - 2]) && r(n) :
a
)
.filter(v => !(v % 2))
//.reduce((s, v) => s+=v, 0)
console.log(r(56))
It is giving correct array but when I wanted to calculate the sum (using reduce method by commenting the last line) it is giving 0 as a result
let a = [1, 2];
const r = (n) =>
Array.from(
a[a.length - 1] + a[a.length - 2] <= n ?
a.push(a[a.length - 1] + a[a.length - 2]) && r(n) :
a
)
.filter(v => !(v % 2))
.reduce((s, v) => s+=v, 0)
console.log(r(56))
in Repl.it (Link - https://repl.it/#rahul4sap/1). However, when I try to paste the same in Chrome Dev tools it is giving correct output. Can someone please help me explain why different behavior in Chrome Dev tool and Repl.it (same behaviour I see in local Node server)
Also, it will be good if someone please help me in fixing this as well (Please note I wanted to solve this in as much Functional way as possible)
Thanks in advance!
You could separate the functions an dget the fibonacci array first and then filter the array, and so on.
This approach uses a recursion by handing over a new build array.
const
add = (a, b) => a + b,
f = (n, a = [1, 2]) => a[a.length - 1] + a[a.length - 2] < n
? f(n, [...a, a[a.length - 1] + a[a.length - 2]])
: a,
r = n => f(n)
.filter(v => !(v % 2))
.reduce(add, 0);
console.log(r(56));
Consider a simple recursive function, fibs -
const fibs = (n = 0, a = 0, b = 1) =>
n <= 0
? []
: [ a, ...fibs(n - 1, b, a + b) ]
console.log(fibs(10)) // first 10 fib numbers
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]
Now add your .filter -
const fibs = (n = 0, a = 0, b = 1) =>
n <= 0
? []
: [ a, ...fibs(n - 1, b, a + b) ]
const evens =
fibs(10)
.filter(n => !(n & 1))
console.log(evens)
// [ 0, 2, 8, 34 ]
Now add your .reduce -
const fibs = (n = 0, a = 0, b = 1) =>
n <= 0
? []
: [ a, ...fibs(n - 1, b, a + b) ]
const sumEvens =
fibs(10)
.filter(n => !(n & 1))
.reduce((r, n) => r + n, 0)
console.log(sumEvens)
// 44
To see how you can compute fibonacci using other functional programming techniques, see this recent Q&A
Thank you for this. But I am looking for pushing element in an array (probably in a single function) until certain condition is met (like create Fibbonacci array until the last element is less than 100).
You change n = 0 to until = 0 and change the exit condition of your loop from n <= 0 to a > until -
const fibs = (until = 0, a = 0, b = 1) =>
a > until
? []
: [ a, ...fibs(until, b, a + b) ]
console.log(fibs(100))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ]
const sumEvens =
fibs(100)
.filter(n => !(n & 1))
.reduce((r, n) => r + n, 0)
console.log(sumEvens)
// 4
You may receive result in one line when you know how many fibonacci numbers do you need.
For example this code filter even numbers from the first 10 fibonacci numbers and calculate their sum:
let arr = (n) => [1, 2, ...Array(n-2)].reduce((acc, rec, idx) => (idx < 2) ? [...acc, rec] : [...acc, (acc[idx-2] + acc[idx-1])],[])
.filter(it => !(it % 2))
.reduce((s, v) => s+=v, 0)
console.log(arr(10))

Find average of each array within an array

I'm trying to write a map/reduce to get the average of each array within an array.
For example.
[[1][2,3][4,5,6,7]] => [1, 2.5, 5.5]
Right now this is my code where result is the array of arrays:
result.map(array => {
return array.reduce((a, b) => (a + b)) / array.length;
})
const result = [
[1],
[2, 3],
[4, 5, 6, 7]
]
console.log(result.map(array => {
return array.reduce((a, b) => (a + b)) / array.length;
}))
Any help to get the desired output is much appreciated. As it stands, my output is reducing to an array of NaN's instead of the averages.
You need a closing parentesis.
By using Array#reduce with arrays with unknown length, you need to take a start value, which is in this case of a length of zero the result.
var result = [[1], [2, 3], [4, 5, 6, 7]],
avg = result.map(array => array.reduce((a, b) => a + b, 0) / array.length);
// ^^^ ^
// optional required
console.log(avg);
you must provide a second argument to the reduce function, the initial value of a. So:
result.map(array => {
return array.reduce((a, b) => a + b, 0) / array.length;
});
You may also want to ensure that array.length > 0 before you divide by it

Sort an array in a peculiar order

I've been trying to figure out how to solve this problem but I can't seem to find the proper sorting order.
Instructions:
Write a program that orders a list of numbers in the following way:
3,-2,1,0,-1,0,-2,1 => -2,-1,-2,0,0,3,1,1
'use strict';
let myNumbers = '3,-2,1,0,-1,0,-2,1';
// I receive the input as a string and split and map it into an array
let myNumbers = gets().split(',').map(Number);
I've tried applying the sort() method in ascending order to all integers below zero and doing the opposite for those above but that's not quite the order in the expected output.
I've also attempted to splice the first array after applying sort() to 0 and then re-arrange the spliced part and concatenate it. However, that won't work with all test inputs.
Another example:
3,-12,0,0,13,5,1,0,-2 => -12,-2,0,0,0,3,13,5,1
What is the logic in this order? Thanks.
Because this sounds like the solution to a homework problem or something of the like, I'll let you write the code:) But the way I would do it is in one iteration through the array, create three separate arrays:
Negative numbers
0s
Positive numbers
Squish the arrays together without sorting and you have your O(N) solution.
So based on sketrik answer which covers the logic, this is the code:
const myNumbers = '3,-2,1,0,-1,0,-2,1';
const arr = myNumbers.split(',').map(Number)
const res = arr.filter(i => i < 0)
.concat(arr.filter(i => i === 0))
.concat(arr.filter(i => i > 0))
console.log(res)
This works thanks to two very basic JS methods of Array.prototype:
concat and filter. I could not explain them better than the documentation, check it out!
But basically, what I am doing is:
find the chunk with negatives with arr.filter(i => i < 0)
find the chunk with zeros with arr.filter(i => i === 0)
find the chunk with positives with arr.filter(i => i > 0)
concat them all into one array.
I am Neo.
'use strict';
let myInput = '3,-2,1,0,-1,0,-2,1';
let myNumbers = myInput.split(',').map(Number);
let negatives = [];
let zeroes = [];
let positives = [];
for (const element of myNumbers) {
if (element < 0) {
negatives.push(element);
} else if (element === 0) {
zeroes.push(element);
} else if (element > 0) {
positives.push(element);
}
}
let sortedArr = negatives.concat(zeroes, positives);
console.log(sortedArr.join(','));
Logic or Typo?
"...ascending order to all integers below zero and doing the opposite for those above..."
Following what was posted in question the examples should be:
-2, -2, -1, 0, 0, 3, 1, 1 and -12, -2, 0, 0, 0, 13, 5, 3, 1
Zero and less ascending: -3, -2, -1, 0. Greater than zero descending: 3, 2, 1
To get those results see Demo 1.
Strictly going by the examples is simpler:
-2, -1, -2, 0, 0, 3, 1, 1 and -12, -2, 0, 0, 0, 3, 13, 5, 1
Group negative numbers, then zeros, and then positive numbers: [-][0][+]. No order within the three arrays is required. Order is only required for the three groups.
To get those results see Demo 2.
Explanation
Demo 1
First, sort array in ascending order:
const ordered = array.sort((current, next) => current - next);
Next, find the index of the first number that's greater than 0, then extract all numbers beginning at that index and ending at the last number. Store the extracted array in a variable:
const positive = ordered.splice(ordered.findIndex(number => number > 0));
Finally, sort extracted array in descending order and then concatenate the extracted array to the end of the original array:
return ordered.concat(positive.sort((current, next) => next - current));
Demo 2
Create three new arrays returned by the filter() method: negative (n < 0), zero (n === 0), and positive (n > 0).
Then concatenate them into one array:
const negative = array.filter(number => number < 0);
const zero = array.filter(number => number === 0);
const positive = array.filter(number => number > 0);
return negative.concat(zero, positive);
Demo 1
const unorderedA = [3, -2, 1, 0, -1, 0, -2, 1];
const unorderedB = [3, -12, 0, 0, 13, 5, 1, 0, -2];
const illogical = array => {
const ordered = array.sort((current, next) => current - next);
const positive = ordered.splice(ordered.findIndex(number => number > 0));
return ordered.concat(positive.sort((current, next) => next - current));
};
// For demonstration purposes
const log = data => {
const string = Array.isArray(data) ? `[${data.join(', ')}]` : data;
return console.log(string);
};
log(illogical(unorderedA));
log(illogical(unorderedB));
Demo 2
const unorderedA = [3, -2, 1, 0, -1, 0, -2, 1];
const unorderedB = [3, -12, 0, 0, 13, 5, 1, 0, -2];
const illogical = array => {
const negative = array.filter(number => number < 0);
const zero = array.filter(number => number === 0);
const positive = array.filter(number => number > 0);
return negative.concat(zero, positive);
};
// For demonstration purposes
const log = data => {
const string = Array.isArray(data) ? `[${data.join(', ')}]` : data;
return console.log(string);
};
log(illogical(unorderedA));
log(illogical(unorderedB));

Categories