JavaScript sum function - javascript

I have stacked in the sum of an array. The code is bellow
function User(name,email) {
this.name = name;
this.email = email;
this.cartAmount = [];
this.total = 0;
}
User.prototype = {
constructor: User,
addCart: function(mrp){
this.cartAmount.push(mrp);
},
changeEmail: function(newmail){
this.email = newmail;
},
showCart: function() {
var cart = this.cartAmount.length >0 ? this.cartAmount.join("tk,") : "No product in the cart";
return this.name+" has "+cart+" in his cart.";
},
intotal: function(){
for(var n in this.cartAmount){
this.total += this.cartAmount[n];
return this.total;
}
}
};
athar= new User("Athar Jamil", "atharjamil#gmail.com");
console.log(athar.name);
athar.changeEmail("atharjamil#yahoo.com");
console.log(athar.email);
athar.addCart(20);
athar.addCart(50);
athar.addCart(80);
console.log(athar.intotal());
It shows me only 20 as the result of the sum. What is the problem?

You're returning too early, hence your for loop runs only once and returns the first item in the cart.
Try this instead:
intotal: function(){
for(var n in this.cartAmount){
this.total += this.cartAmount[n];
}
return this.total;
}

Do not use this.total for that. If you call this method several times, your total will increase each time you call it. You should at least put a this.total = 0 at the top of your method.
I personally would have written it like this instead :
intotal: function(){
var out = 0;
for(var n in this.cartAmount){
out += this.cartAmount[n];
}
return out;
}

Using Array.prototype.reduce() you can simplify that function a lot:
intotal: function() {
return this.cartAmount.reduce((a, b)=> a + b)
}
From MDN:
The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
Here you pass an arrow function to the reduce method, which takes two arguments: a and b, and returns sum of them.

intotal function returning the first element of cartAmount array.
Place the return statement of intotal function outside of for loop.

function sum(){
var args = Array.prototype.slice.call(arguments);
return args.reduce(function(pre,curr){
if(!isNaN(curr)){
return pre+curr;
}
else
{
throw Error("Non-Numeric arguments"+curr);
}
},0)
}
var result = sum(12,13,14); //pass any number of parameter to sum
alert("Sum Is:"+result);

https://www.npmjs.com/package/mnjs
First import sum function from mnjs package
<script src="https://cdn.jsdelivr.net/npm/mnjs/browser/index.js"></script>
or
const { sum } = require('mnjs')
or
import { sum } from 'mnjs'
Then use sum function as follow:
const cartAmount = [1, 4, 2]
sum(cartAmount) // returns 7
https://runkit.com/dr-montasir/mnjs-sum-function

Related

Add multiple variable passed as parameter to function currying

How can I achieve these scenarios using function currying?
add(3,4)(3)
add(3)(4)(3)
add(3)(4,3)
I have read so many blogs not able to find this kind of scenario. can someone help me on this.
Something like this?
var total = 0;
function add(){
// Add up every argument received
for (var i in arguments)
total += arguments[i];
return add;
}
add(3,4)(3);
console.log(total);
add(3)(4)(3);
console.log(total);
add(3)(4,3);
console.log(total);
Update
If you do not want the function to depend on global variable, save the value as an attribute of add function instead
function add(){
// Add up every argument received
for (var i in arguments)
add.total += arguments[i];
return add;
}
add.total = 0;
add.toString = function(){
var total = add.total;
add.total = 0;
return total;
};
var sum1 = add(3,4)(3);
alert( sum1 );
var sum2 = add(3)(4)(3);
alert( sum2 );
var sum3 = add(3)(4,3);
alert( sum3 );
I see two currying scenarios here:
1.
add(3,4)(3)
add(3)(4,3)
and
2.
add(3)(4)(3)
The first one you can address with:
function add() {
const args1 = Array.prototype.slice.call(arguments);
return function() {
const args2 = Array.prototype.slice.call(arguments);
return args1.concat(args2).reduce(function(a, i) { return a + i });
}
}
The second one with:
function add() {
const args1 = Array.prototype.slice.call(arguments);
return function() {
const args2 = Array.prototype.slice.call(arguments);
return function() {
const args3 = Array.prototype.slice.call(arguments);
return args1.concat(args2).concat(args3).reduce(function(a, i) { return a + i });
}
}
}
I did not find a solution to have a function which tackles both at the same time.

How to sort and list out the array element, after comparing the sums of each numeric value

This code returns only returns the order of the sums of the numeric value, how do I return the array element in a list arranged by largest sum on top?
For instance, the result should be:
"1234-2722-2343-2842"
"1234-2722-2343-2345"
"1234-2322-2343-2342"
Code:
var addSum = function(ccNum) {
var sum = 0;
for (var i=0; i<ccNum.length; i++ ) {
var eachLetter = ccNum.charAt(i);
if (!isNaN(eachLetter)) {
sum += +eachLetter;
}
}
return sum;
};
var ccNums = ["1234-2322-2343-2342","1234-2722-2343-2345", "1234-2722-2343-2842"];
var checkNums = [];
for (var i=0; i<ccNums.length; i++) {
var ccNum = ccNums[i];
var sum = addSum(ccNum);
console.log("The checksum of CC number:"+ccNum+" is "+sum);
checkNums.push(sum);
}
checkNums.sort(function(a,b) {
return b-a;
});
console.log(checkNums);
The solution using String.replace, String.split, Array.map, Array.filter and Array.reduce:
var ccNums = ["1234-2322-2343-2342","1234-2722-2343-2345", "1234-2722-2343-2842"],
getSum = function(num){
return num.replace("-", "").split("").map(Number).filter(Boolean).reduce(function(prev, next){
return prev + next;
});
};
ccNums.sort(function (a, b) {
return getSum(b) - getSum(a);
});
console.log(ccNums);
The output:
["1234-2722-2343-2842", "1234-2722-2343-2345", "1234-2322-2343-2342"]
I suggest use Sorting with map, because it uses only one iteration for the sum of a string and uses it until the sorts end. Then it rebuilds a new array with the sorted items.
var ccNums = ["1234-2322-2343-2342", "1234-2722-2343-2345", "1234-2722-2343-2842"];
// temporary array holds objects with position and sort-value
var mapped = ccNums.map(function (el, i) {
return {
index: i,
value: el.split('').reduce(function (r, a) { return r + (+a || 0); }, 0)
};
});
// sorting the mapped array containing the reduced values
mapped.sort(function (a, b) {
return b.value - a.value;
});
// container for the resulting order
var result = mapped.map(function (el) {
return ccNums[el.index];
});
console.log(result);
Use Array#sort with help of String#split and Array#reduce methods
var ccNums = ["1234-2322-2343-2342", "1234-2722-2343-2345", "1234-2722-2343-2842"];
// function to get sum of numbers in string
function sum(str) {
// split string
return str.split('-')
// iterate and get sum
.reduce(function(a, b) {
// parse string to convert to number
return a + Number(b); // in case string contains no-digit char that for avoiding NaN use "return a + ( parseInt(b, 10) || 0 )
}, 0); //set initial value to avoid 2 parsing
}
// call sort function
ccNums.sort(function(a, b) {
// find out sum and compare based on that
return sum(b) - sum(a);
});
console.log(ccNums)
Or much better way would be, store the sum in an object and refer in sort function which helps avoid calling sum function multiple times.
var ccNums = ["1234-2322-2343-2342", "1234-2722-2343-2345", "1234-2722-2343-2842"];
// function to get sum of numbers in string
function sum(str) {
// split string
return str.split('-')
// iterate and get sum
.reduce(function(a, b) {
// parse string to convert to number
return a + Number(b);
}, 0); //set initial value to avoid 2 parsing
}
var sumArr = {};
// create object for referncing sum,
// which helps to avoid calling sum function
// multiple tyms with same string
ccNums.forEach(function(v) {
sumArr[v] = sum(v);
});
// call sort function
ccNums.sort(function(a, b) {
// find out sum and compare based on that
return sumArr[b] - sumArr[a];
});
console.log(ccNums)

Currying a function that takes infinite arguments

Using ES5, how do you curry a function that takes infinite arguments.
function add(a, b, c) {
return a + b + c;
}
The function above takes only three arguments but we want our curried version to be able to take infinite arguments.
Hence, of all the following test cases should pass:
var test = add(1);
test(2); //should return 3
test(2,3); //should return 6
test(4,5,6); //should return 16
Here is the solution that I came up with:
function add(a, b, c) {
var args = Array.prototype.slice.call(arguments);
return function () {
var secondArgs = Array.prototype.slice.call(arguments);
var totalArguments = secondArgs.concat(args);
var sum = 0;
for (i = 0; i < totalArguments.length; i++) {
sum += totalArguments[0];
}
return sum;
}
}
However, I have been told that it's not very “functional” in style.
Part of the reason your add function is not very "functional" is because it is attempting to do more than just add up numbers passed to it. It would be confusing for other developers to look at your code, see an add function, and when they call it, get a function returned to them instead of the sum.
For example:
//Using your add function, I'm expecting 6
add(1,2,3) //Returns another function = confusing!
The functional approach
The functional approach would be to create a function that allows you to curry any other functions, and simplify your add function:
function curry(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments, 0)
));
}
}
function add() {
var args = Array.prototype.slice.call(arguments);
return args.reduce(function (previousValue, currentValue) {
return previousValue + currentValue;
});
}
Now, if you want to curry this function, you would just do:
var curry1 = curry(add, 1);
console.log(
curry1(2), // Logs 3
curry1(2, 3), // Logs 6
curry1(4, 5, 6) // Logs 16
);
//You can do this with as many arguments as you want
var curry15 = curry(add, 1,2,3,4,5);
console.log(curry15(6,7,8,9)); // Logs 45
If I still want to add 1, 2, 3 up I can just do:
add(1,2,3) //Returns 6, AWESOME!
Continuing the functional approach
This code is now becoming reusable from everywhere.
You can use that curry function to make other curried function references without any additional hassle.
Sticking with the math theme, lets say we had a multiply function that multiplied all numbers passed to it:
function multiply() {
var args = Array.prototype.slice.call(arguments);
return args.reduce(function (previousValue, currentValue) {
return previousValue * currentValue;
});
}
multiply(2,4,8) // Returns 64
var curryMultiply2 = curry(multiply, 2);
curryMultiply2(4,8) // Returns 64
This functional currying approach allows you take that approach to any function, not just mathematical ones. Although the supplied curry function does not support all edge cases, it offers a functional, simple solution to your problem that can easily be built upon.
Method 1: Using partial
A simple solution would be to use partial as follows:
Function.prototype.partial = function () {
var args = Array.prototype.concat.apply([null], arguments);
return Function.prototype.bind.apply(this, args);
};
var test = add.partial(1);
alert(test(2)); // 3
alert(test(2,3)); // 6
alert(test(4,5,6)); // 16
function add() {
var sum = 0;
var length = arguments.length;
for (var i = 0; i < length; i++)
sum += arguments[i];
return sum;
}
Method 2: Single Level Currying
If you only want one level of currying then this is what I would do:
var test = add(1);
alert(test(2)); // 3
alert(test(2,3)); // 6
alert(test(4,5,6)); // 16
function add() {
var runningTotal = 0;
var length = arguments.length;
for (var i = 0; i < length; i++)
runningTotal += arguments[i];
return function () {
var sum = runningTotal;
var length = arguments.length;
for (var i = 0; i < length; i++)
sum += arguments[i];
return sum;
};
}
Method 3: Infinite Level Currying
Now, here's a more general solution with infinite levels of currying:
var add = running(0);
var test = add(1);
alert(+test(2)); // 3
alert(+test(2,3)); // 6
alert(+test(4,5,6)); // 16
function running(total) {
var summation = function () {
var sum = total;
var length = arguments.length;
for (var i = 0; i < length; i++)
sum += arguments[i];
return running(sum);
}
summation.valueOf = function () {
return total;
};
return summation;
}
A running total is the intermediate result of a summation. The running function returns another function which can be treated as a number (e.g. you can do 2 * running(21)). However, because it's also a function you can apply it (e.g. you can do running(21)(21)). It works because JavaScript uses the valueOf method to automatically coerce objects into primitives.
Furthermore, the function produced by running is recursively curried allowing you to apply it as many times to as many arguments as you wish.
var resultA = running(0);
var resultB = resultA(1,2);
var resultC = resultB(3,4,5);
var resultD = resultC(6,7,8,9);
alert(resultD + resultD(10)); // 100
function running(total) {
var summation = function () {
var sum = total;
var length = arguments.length;
for (var i = 0; i < length; i++)
sum += arguments[i];
return running(sum);
}
summation.valueOf = function () {
return total;
};
return summation;
}
The only thing you need to be aware of is that sometimes you need to manually coerce the result of running into a number by either applying the unary plus operator to it or calling its valueOf method directly.
Similar to the above problem. Sum of nth level curry by recursion
Trick: To stop the recursion I'm passing last () as blank**
function sum(num1) {
return (num2) => {
if(!num2) {
return num1;
}
return sum(num1 + num2);
}
}
console.log('Sum :', sum(1)(2)(3)(4)(5)(6)(7)(8)())
There is more generic approach by defining a curry function that takes minimum number of arguments when it evaluates the inner function. Let me use ES6 first (ES5 later), since it makes it more transparent:
var curry = (n, f, ...a) => a.length >= n
? f(...a)
: (...ia) => curry(n, f, ...[...a, ...ia]);
Then define a function that sums all arguments:
var sum = (...args) => args.reduce((a, b) => a + b);
then we can curry it, telling that it should wait until at least 2 arguments:
var add = curry(2, sum);
Then it all fits into place:
add(1, 2, 3) // returns 6
var add1 = add(1);
add1(2) // returns 3
add1(2,3) // returns 6
add1(4,5,6) // returns 16
You can even skip creating add by providing the first argument(s):
var add1 = curry(2, sum, 1);
ES5 version of curry is not as pretty for the lack of ... operator:
function curry(n, f) {
var a = [].slice.call(arguments, 2);
return a.length >= n
? f.apply(null, a)
: function () {
var ia = [].slice.call(arguments);
return curry.apply(null, [n, f].concat(a).concat(ia));
};
}
function sum() {
return [].slice.call(arguments).reduce(function (a, b) {
return a + b;
});
};
The rest is the same...
Note: If efficiency is a concern, you may not want to use slice on arguments, but copy it to a new array explicitly.
Bit late in this game, but here is my two cents. Basically this exploits the fact that functions are also objects in JavaScript.
function add(x) {
if (x === undefined) {
return add.numbers.reduce((acc, elem) => acc + elem, 0);
} else {
if (add.numbers) {
add.numbers.push(x);
} else {
add.numbers = [x];
}
}
return add;
}
Infinite sum with currying, you can pass a single parameter or multiple up-to infinite:
function adding(...arg) {
return function clousureReturn(...arg1) {
if (!arguments.length) {
let finalArr = [...arg, ...arg1];
let total = finalArr.reduce((sum, ele) => sum + ele);
return total;
}
return adding(...arg, ...arg1)
}
}
This is my solution for single level currying
function sum() {
let args = [...arguments];
let total = args.reduce((total,num) => total + num,0);
return total;
}
console.log(sum(1,2,3,4)) // 10
and the solution for infinite level currying
let sum= function (...args1) {
let total =args1.reduce((total,num) => total + num,0)
return function(...args2) {
if(args2.length!== 0) {
let total2 = args2.reduce((total,num)=>total + num,0);
return sum(total,total2);
}
return total;
};
};
console.log(sum(2,3,4)(2,3)(1)()); // 15
Simple solution
const add = (one) => { // one: Parameter passed in test
return (...args) => {
// args: Array with all the parameters passed in test
return one + args.reduce((sum, i) => sum + i, 0) // using reduce for doing sum
}
}
var test = add(1);
console.log(test(2)); //should return 3
console.log(test(2, 3)); //should return 6
console.log(test(4, 5, 6)); //should return 16

Compute value for different properties of object

Given an array of objects
function Example(x, y){
this.prop1 = x;
this.prop2 = y;
}
var exampleArray = new Array();
exampleArray.push(nex Example(0,1));
exampleArray.push(nex Example(1,3));
Now I would like to add a function which computes the average for one of the properties
function calcAvg(exampleArray, 'prop1') -> 0.5
function calcAvg(exampleArray, 'prop2') -> 2
If I don't want to use jQuery or other libraries, is there a generic way to do this?
Solution with Array.prototype.reduce method and check for valid property:
function Example(x, y) {
this.prop1 = x;
this.prop2 = y;
}
var exampleArray = new Array();
exampleArray.push(new Example(0, 1));
exampleArray.push(new Example(1, 3));
function calcAvg(arr, prop) {
if (typeof arr[0] === 'object' && !arr[0].hasOwnProperty(prop)) {
throw new Error(prop + " doesn't exist in objects within specified array!");
}
var avg = arr.reduce(function(prevObj, nextObj){
return prevObj[prop] + nextObj[prop];
});
return avg/arr.length;
}
console.log(calcAvg(exampleArray, 'prop2')); // output: 2
I think it will work ,
You need to iterate through all Example objects in the array and add the given property's value in a variable e.g. sum and then at the end divide it by total number of objects in the array to get average.
console.log(avg(exampleArray, 'prop1'));
function avg (array, propName){
var sum = 0;
array.forEach(function(exm){
sum+= exm[propName];
});
return sum / array.length;
}
You can use Array.prototype.reduce() for it.
The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
function Example(x, y) {
this.prop1 = x;
this.prop2 = y;
}
function calcAvg(array, key) {
return array.reduce(function (r, a) {
return r + a[key];
}, 0) / array.length;
}
var exampleArray = [new Example(0, 1), new Example(1, 3)],
avgProp1 = calcAvg(exampleArray, 'prop1'),
avgProp2 = calcAvg(exampleArray, 'prop2');
document.write(avgProp1 + '<br>');
document.write(avgProp2);
This code iterates over every value of arr, searches for property prop in every value, pushes the value of that property to an array named values and returns the sum of all the values in values divided by the number of values in it.
function calcAvg(arr,prop){
var values = [];
for(var i = 0; i<arr.length; i++){
values.push(arr[i][prop]);
}
var sum = values.reduce(function(prev,current){
return prev+current;
});
return sum/values.length;
}
Demo is here.

convert the following code from a for-loop to Array#map

i am working on simple js function...
I am trying to convert the following code from a for-loop to Array#map
providing my code below in the fiddle..
bnasically i am trying to learn array map..
http://jsfiddle.net/newtdms2/
function doubleAll(numbers) {
var result = [];
result = numbers.map(function(num) {
for (var i = 0; i < numbers.length; i++) {
result.push(numbers[i] * 2)
}
return result;
});
}
module.exports = doubleAll
You don't have to create a for loop in your map, map will call the function callback on each element of the array you pass as parameter. So just try something like :
function doubleAll(numbers) {
return numbers.map(function (num) {
return num * 2;
});
}
Here is the doc for the map method, could be interesting to you !
Your for inside map is not required:
function doubleAll(numbers) {
var result = [];
result = numbers.map(function(num) {
return (num * 2);
});
return result;
}
And simpler can be:
function doubleAll(numbers) {
return numbers.map(function(num) {
return (num * 2);
});
}
Array.prototype.map: will loop once through each element in an array. It receives a callback function as the argument and the callback function takes three arguments, being the first 2:
currentItem: The element being processed in the array in the example above num.
index: The index of the element being processed in the array, in for loop this will be i.
function doubleAll(numbers) {
return numbers.map(num => num*2);
}

Categories