Is Possible To Reduce The Complexity And Spaghetti Quality Of This Javascript Algorithm Solution?
Solution 1:
functionaddTogether(a, b) {
if (typeof a == "number") {
if (arguments.length == 1) {
returnb =>addTogether(a, b);
} elseif (typeof b == "number") {
return a + b;
}
}
}
// as per OP's code// returns 3console.log("addTogether(1, 2) = " + addTogether(1, 2));
console.log("addTogether(1, 2, 3) = " + addTogether(1, 2, 3));
console.log("addTogether(1)(2) = " + addTogether(1)(2));
console.log("addTogether(1)(2, 3) = " + addTogether(1)(2, 3));
console.log("addTogether(1, 2, '3') = " + addTogether(1, 2, '3'));
console.log("addTogether(1)(2, '3') = " + addTogether(1)(2, '3'));
console.log("addTogether(1, 2, [3]) = " + addTogether(1, 2, [3]));
console.log("addTogether(1)(2, [3]) = " + addTogether(1)(2, [3]));
console.log("addTogether(1, 2, NaN) = " + addTogether(1, 2, NaN));
console.log("addTogether(1)(2, NaN) = " + addTogether(1)(2, NaN));
// returns NaNconsole.log("addTogether(1, NaN) = " + addTogether(1, NaN));
console.log("addTogether(1)(NaN) = " + addTogether(1)(NaN));
// returns undefinedconsole.log("addTogether() = " + addTogether());
console.log("addTogether(1)() = " + addTogether(1)());
console.log("addTogether('1') = " + addTogether('1'));
console.log("addTogether(1, '2') = " + addTogether(1, '2'));
console.log("addTogether(1)('2') = " + addTogether(1)('2'));
console.log("addTogether(1, [2]) = " + addTogether(1, [2]));
console.log("addTogether(1)([2]) = " + addTogether(1)([2]));
The following improvements have been suggested, but they would change the semantics of OPs code:
- return
undefined
ifa
orb
isNaN
, asNaN
is not a 'valid number' - return
undefined
if more than two arguments are provided instead of silently dropping them (thanks @PatrickRoberts)
If you don't mind returning a function for e. g. addTogether('x')
, use:
functionaddTogether(a, b) {
if (arguments.length == 1) {
returnb =>addTogether(a, b);
} elseif (typeof a == "number" && typeof b == "number") {
return a + b;
}
}
This way, your will always return a function
for one argument and Number
or undefined
for two or more arguments = more robust code.
For ES5 compatibility and if you don't mind addTogether(2)()
returning a function, replace b => addTogether(a, b)
with addTogether.bind(undefined, a)
(thanks @PatrickRoberts).
Solution 2:
You can use spread operator for improving your function and some Array
functions like some
or reduce
:
In that way addTogether
can accept more than one argument.
If addTogether
is called with one argument, the function returned can be called with more than one arguments too.
letisNotNumber = number=> typeof number != 'number';
let addTogether = function(...numbers){
if(!numbers.length) return;
if(numbers.length == 1){
if(isNotNumber(numbers[0])) return;
returnfunction(...otherNumbers){
if(otherNumbers.some(isNotNumber)) return;
return otherNumbers.reduce((prev, curr)=> prev + curr, numbers[0]);
}
} else {
if(numbers.some(isNotNumber)) return;
return numbers.reduce((prev, curr)=> prev + curr);
}
}
// Will return a valueconsole.log(addTogether(1,2,3));
console.log(addTogether(1)(2,3));
// Will return undefinedconsole.log(addTogether(1, [2]));
console.log(addTogether(1)('2'));
console.log(addTogether(1)([2]));
console.log(addTogether());
Solution 3:
According to jscomplexity.org, OP's function has a cyclomatic complexity of 8 while the solution below have a cyclomatic complexity of 5 (based on the Babel ES5 transpilation).
This solution is functionally equivalent to OP's code, see tests below:
'use strict';
functionaddTogether(...augends) {
if (augends.slice(0, 2).every(value =>typeof value === 'number')) {
switch (augends.length) {
case0:
return;
case1:
return(addend) =>addTogether(augends[0], addend);
default:
return augends[0] + augends[1];
}
}
}
// should work (returns 3)console.log("addTogether(1, 2) = " + addTogether(1, 2));
console.log("addTogether(1, 2, 3) = " + addTogether(1, 2, 3));
console.log("addTogether(1)(2) = " + addTogether(1)(2));
console.log("addTogether(1)(2, 3) = " + addTogether(1)(2, 3));
console.log("addTogether(1, 2, '3') = " + addTogether(1, 2, '3'));
console.log("addTogether(1)(2, '3') = " + addTogether(1)(2, '3'));
console.log("addTogether(1, 2, [3]) = " + addTogether(1, 2, [3]));
console.log("addTogether(1)(2, [3]) = " + addTogether(1)(2, [3]));
console.log("addTogether(1, 2, NaN) = " + addTogether(1, 2, NaN));
console.log("addTogether(1)(2, NaN) = " + addTogether(1)(2, NaN));
// should return NaN (not sure if this "works" or not)console.log("addTogether(1, NaN) = " + addTogether(1, NaN));
console.log("addTogether(1)(NaN) = " + addTogether(1)(NaN));
// should not work (returns undefined)console.log("addTogether() = " + addTogether());
console.log("addTogether(1)() = " + addTogether(1)());
console.log("addTogether('1') = " + addTogether('1'));
console.log("addTogether(1, '2') = " + addTogether(1, '2'));
console.log("addTogether(1)('2') = " + addTogether(1)('2'));
console.log("addTogether(1, [2]) = " + addTogether(1, [2]));
console.log("addTogether(1)([2]) = " + addTogether(1)([2]));
For reference, here is my other solution which prohibits extraneous arguments and also tests against literal NaN
values (which ironically are typeof "number"
). Edit Unfortunately due to fixing the implementation for the test case console.log("addTogether(1)() = " + addTogether(1)());
, it now has a cyclomatic complexity of 7:
'use strict';
functionaddTogether(...augends) {
if (augends.every(value =>typeof value === 'number' && !isNaN(value))) {
switch (augends.length) {
case1:
return(addend, ...addends) =>addTogether(augends[0], addend, ...addends);
case2:
return augends[0] + augends[1];
}
}
}
// should work (returns 3)console.log("addTogether(1, 2) = " + addTogether(1, 2));
console.log("addTogether(1)(2) = " + addTogether(1)(2));
// should not work (returns undefined)console.log("addTogether() = " + addTogether());
console.log("addTogether(1)() = " + addTogether(1)());
console.log("addTogether('1') = " + addTogether('1'));
console.log("addTogether(1, 2, 3) = " + addTogether(1, 2, 3));
console.log("addTogether(1, '2') = " + addTogether(1, '2'));
console.log("addTogether(1)('2') = " + addTogether(1)('2'));
console.log("addTogether(1, [2]) = " + addTogether(1, [2]));
console.log("addTogether(1)([2]) = " + addTogether(1)([2]));
console.log("addTogether(1)(2, 3) = " + addTogether(1)(2, 3));
console.log("addTogether(1, 2, '3') = " + addTogether(1, 2, '3'));
console.log("addTogether(1)(2, '3') = " + addTogether(1)(2, '3'));
console.log("addTogether(1, 2, [3]) = " + addTogether(1, 2, [3]));
console.log("addTogether(1)(2, [3]) = " + addTogether(1)(2, [3]));
console.log("addTogether(1, 2, NaN) = " + addTogether(1, 2, NaN));
console.log("addTogether(1)(2, NaN) = " + addTogether(1)(2, NaN));
console.log("addTogether(1, NaN) = " + addTogether(1, NaN));
console.log("addTogether(1)(NaN) = " + addTogether(1)(NaN));
Solution 4:
Why you don't provide arguments to function. I think that this is the simplest vay:
functionadd(arg1, arg2) {
if (isNan(arg1) || isNan(arg2)) returnundefined;
if (!arg2) {
returnfunctionName(arg1);
}
return arg1 + arg2;
}
Solution 5:
You should read about function currying, bind, call, and apply. Currying is applicable to ES6, but bind,call and apply run everywhere.
Details on the MDN site https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
In short, the solution you are looking for is:
functionaddTogether(a,b) {
return a+b;
}
console.log(typeof addTogether); //-->functionconsole.log(typeof addTogether.bind(null,2)); //-->functionconsole.log(addTogether.bind(null,2)(3));//5console.log(addTogether(2,3)); //-->5
Yeah, it IS that simple, not kidding!
Post a Comment for "Is Possible To Reduce The Complexity And Spaghetti Quality Of This Javascript Algorithm Solution?"