(JavaScript) Why my if/else code didn't work? [duplicate] - javascript

This question already has answers here:
How do you use the ? : (conditional) operator in JavaScript?
(20 answers)
Closed 1 year ago.
I need to make a fibonacci sequence and I found this code below here. When I try to understand all code I saw "(i <= 1) ? i : arr[i-2] + arr[i-1]", I thought that was an simple if else shortcut condition, and I try to replace by the extended way just to be sure (see the last code). But now the code didn't work...
Stackoverflow code:
function fib(n) {
return new Array(n).fill(1).reduce((arr, _, i) => {
arr.push((i <= 1) ? i : arr[i - 2] + arr[i - 1])
return arr
}, []);
}
console.log(fib(10))
My code with (extended if else):
function fib(n) {
return new Array(n).fill(1).reduce((arr, _, i) => {
arr.push(
if (i <= 1) {
i
} else {
arr[i - 2] + arr[i - 1]
})
return arr
}, []);
}
console.log(fib(10))
Why my code is not equivalent to the code above?

Basically what #esqew said.
“I thought that was an simple if else shortcut condition” While this
is kind of close to true, any old if/else is not a drop-in
replacement for something that was originally written using the
ternary operator ?
Replacing a Conditional Operator with an if statement directly will throw an error.
If you want to use if/else syntax inside a function parameter you could write the code as a function in the form of an IIFE.
(() => {
if (i <= 1) {
return i;
} else {
return arr[i - 2] + arr[i - 1];
}
})();
Demo:
function fib(n) {
return new Array(n).fill(1).reduce((arr, _, i) => {
arr.push(
(() => {
if (i <= 1) {
return i;
} else {
return arr[i - 2] + arr[i - 1];
}
})()
);
return arr;
}, []);
}
console.log(fib(10));

Related

Sum of Digits / Digital Root codewars kata [duplicate]

This question already has answers here:
Recursive function returns undefined
(3 answers)
Closed 1 year ago.
Please, help me. I don't understand. Why second solution returns undefined?
function digital_root(n) {
return n < 10 ? n : digital_root(n.toString().split('').map(Number).reduce((a, b) => a + b));
}
console.log(digital_root(12345678));
// expected output: 9
function digital_root(n) {
if (n < 10) {
return n;
} else {
digital_root(n.toString().split('').map(Number).reduce((a, b) => a + b));
}
}
console.log(digital_root(12345678));
// output: undefined
This happens because your second code ignores the value you get returned from the recursive call. You should do something with it... return it.
function digital_root(n) {
if (n < 10) {
return n;
} else {
return digital_root(n.toString().split('').map(Number).reduce((a, b) => a + b));
}
}
console.log(digital_root(12345678));
Unrelated, but you can combine split and map by doing Array.from. Also the first version joins the two return statements with the conditional operator into a return of one expression:
const digital_root = n => n < 10 ? n
: digital_root(Array.from(n.toString(), Number).reduce((a, b) => a + b));
console.log(digital_root(12345678));

Smallest non-consecutive number in unsorted array

I want to write a function that returns the smallest non-consecutive number of an unsorted array. If the whole array is consecutive, the closest number that would extend the array.
nextId([1,2,3,4]) returns 5
nextId([1,4,3]) returns 2
My try:
function nextId(arr) {
let sortnum = arr.sort((a, b) => a - b);
for (let i = 0; i < arr.length - 1; i++) {
if (sortnum[i] + 1 !== sortnum[i + 1]) {
return sortnum[i] + 1
}
else(sortnum[sortnum.length - 1] === sortnum[sortnum.length - 2] + 1) {
return sortnum[sortnum.length - 1] + 1
}
}
}
If I outcomment the if or else-statement, they both work perfectly fine on their own, yet they don't work for some reason when I put both of them in one statement.
Would have to slice the array to make a copy if that's required, but this will work:
function nextId(arr) {
return arr.sort().find((v, i, a) => v + 1 != a[i + 1]) + 1;
}
console.log(nextId([1,2,3,4]));
console.log(nextId([1,4,3]));
For the case where all the values are subsequent, this works by virtue of the fact that number + 1 != undefined will always evaluate to true.
Just loop your array and compare if current element in sorted array is same as index + 1. If everything is in order, then just arr.length + 1 is next missing item.
function nextId(arr) {
let sortnum = arr.slice().sort((a, b) => a - b);
for (let i = 1; i <= arr.length; i++) {
if (i != sortnum[i - 1]) {
return i;
}
}
return arr.length + 1;
}
console.log(nextId([1,2,3,4]));
console.log(nextId([1,4,3]));

Expanding use of Javascript array.reduce helper method

Background
I am following a course on Udemy which goes over all of the ES6 features. In one of the lessons the instructor talks about using the reduce helper method to solve the popular balance parenthesis interview question.
I can solve this without the reduce method. Although with the reduce method it does get the job done in less code. I have been asked to find the depth of the parenthesis in an interview before and was wondering if this could all be done in the same method using reduce.
I do not know why this addition to the question confuses me so much but I would like to learn.
Problem
I have been trying to figure it out for a while and it might be my lack of understanding how reduce works.
Example
This uses reduce to return true of false regarding if the parenthesis or open and closed evenly.
function balanceParens(string) {
return !string.split("").reduce((counter, char) => {
// Handle if parens open and close out of order
if (counter < 0) { return counter; }
// Add 1 for each open in order
if (char === "(") { return ++counter; }
// subtract 1 for each close in order
if (char === ")") { return --counter; }
// handle use case if char is not a paren
return counter;
}, 0);
}
console.log(balanceParens("((()))"));
Question
How would I return the max depth of the parenthesis using the reduce helper method.
You could maintain current depth and max depth while reducing.
function maxDepth(string) {
return string.split("").reduce(({current, max}, char) => {
// Handle if parens open and close out of order
if (current < 0) return {current, max}
// Add 1 for each open in order
if (char === "(") return { current: current + 1, max: Math.max(max, current + 1)}
// subtract 1 for each close in order
if (char === ")") return { current: current - 1, max}
return {current, max}
}, {current: 0, max: 0}).max;
}
console.log(maxDepth("(((()))(((())))()(((((()))))))"));
Here is a compact version that returns NaN when the parentheses are not balanced. It uses nested functions in a functional style:
function maxDepth(string) {
return ( ([depth, max]) => depth ? NaN : max )
([...string].reduce(([depth, max], ch) =>
(newDepth => [newDepth, newDepth < 0 ? NaN : Math.max(max, newDepth)])
(depth + (ch === "(") - (ch === ")"))
, [0, 0]));
}
console.log(maxDepth("(((()))(((())))()(((((()))))))"));
This should answer it!
function balanceParens(string) {
let max = 0;
let res = string.split("").reduce((counter, char) => {
// Handle if parens open and close out of order
if (counter < 0) {
return counter;
}
// Add 1 for each open in order
if (char === "(") {
if(++counter > max) {
max = counter;
}
return counter;
}
// subtract 1 for each close in order
if (char === ")") {
return --counter;
}
// handle use case if char is not a paren
return counter;
}, 0);
console.log("Max depth was :", max);
return !res;
}
console.log(balanceParens("((()(((())))))((((()))))"));

Javascript palindrome check word to see if it's a palindrome

I'm trying to determine if a word is a palindrome. A palindrome is a word that is spelled the same way forwards and backwards. I want my code to console.log what I've written but I'm getting an error: unreachable code after return statement.
The line where error starts is: isWordAPalindrome('word');?
isWordAPalindrome('word');
function isWordAPalindrome(word) {
var word = "sherpa,stewie,anna,lil squiggle, racecar, tacocat"
str[0];
str.length
console.log(); {
if (str.length = 0) {
return true;
}
if (str[0] != str[str.length - 1]) {
return false;
}
return isWordAPalindrome(str.slice(1, str.length - 1));
isWordAPalindrome('word');
console.log('sherpa');
console.log('stewie');
console.log('anna');
console.log('lil squiggle');
console.log('racecar');
console.log('tacocat');
}
console.log(''); //simply making a newline for easier console reading
console.log('The word provided is: ', word);
isWordAPalindrome('sherpa');
console.log('sherpa is not a palindrome');
isWordAPalindrome('stewie');
console.log('stewie is not a palindrome');
isWordAPalindrome('anna');
console.log('anna is a palindrome');
isWordAPalindrome('lil squiggle');
console.log('lil squiggle is not a palindrome');
isWordAPalindrome('racecar');
console.log('racecar is a palindrome');
isWordAPalindrome('tacocat');
console.log('tacocat is a palindrome');
}
Different approach:
const word = "sherpa,stewie,anna,lil squiggle, A butt tuba, racecar, tacocat";
const a = word.split(',').map(s => s.toLowerCase().replace(/\s+/g, ""));
const isP = s => s === s.split('').reverse().join('');
for (let w of a) {
console.log(`${w}: ${isP(w)}`)
}
You have a return statement which stops the code execution and returns from the function.
Here what you want to achieve
function checkPalindrome(word) {
for (var i = 0, j = word.length -1; i++, j--; i < word.length, j >= 0, i < j) {
if (word.charAt(i) !== word.charAt(j)) {
return false;
}
}
return true;
}
console.log(checkPalindrome('sherpa'));
console.log(checkPalindrome('anna'));
You have code inside the isWordAPalindrom method that is after the return:
return isWordAPalindrome(str.slice(1,str.length-1));
//unreachable
isWordAPalindrome('word');
console.log('sherpa');
console.log('stewie');
...
that code is unreachable
Your recursive routine is fine. You just need to know where to start and end your tabs and braces.
Also, you were assigning the value 0 to your str.length instead of evaluating if it was equal (=== or at the very least ==).
Also, you can evaluate if the word is a palindrome before your print out the log message.
var words = "sherpa, stewie, anna, lil squiggle, racecar, tacocat".split(/,\s*/);
words.forEach(word => {
var isPalindrome = isWordAPalindrome(word);
console.log(`${word} is ${!isPalindrome ? 'not ' : ''}a palindrome`);
});
function isWordAPalindrome(str) {
if (str.length === 0) {
return true;
}
if (str[0] != str[str.length - 1]) {
return false;
}
return isWordAPalindrome(str.slice(1, str.length - 1));
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
Output
sherpa is not a palindrome
stewie is not a palindrome
anna is a palindrome
lil squiggle is not a palindrome
racecar is a palindrome
tacocat is a palindrome
When you do return you are doing your thread "go out" of the function.
Code after return can't be ever executed, it is what the error is saying to you.
If you are trying to do something before the return statement, just put it before.
isWordAPalindrome('word');
console.log('sherpa');
console.log('stewie');
console.log('anna');
console.log('lil squiggle');
console.log('racecar');
console.log('tacocat');
return isWordAPalindrome(str.slice(1, str.length - 1));

Correct method of using eval() when returning values passed as string parameters

I passed string parameters to calculate() function. I need them to be returned as calculated value. In which of below forms I used eval() correctly?
Data:
var nums = ['2','3','1'], sum = ['+'];
First version:
function calculate(a,b,c,d,e)
{
console.log('Calculating...(plus separators): '+a+' '+b+' '+c+' '+d+' '+e);
console.log('Calculating...(comma separators): ',a,' ',b,' ',c,' ',d,' ',e);
console.log('a :',a);
console.log('b :',b);
console.log('c :',c);
console.log('d :',d);
console.log('e :',e);
return eval(a+b+c+d+e);
};
console.log('RESULT: ',calculate(nums[0],sum[0], nums[1],sum[0], nums[2]));
Second version:
function calculateP(a,c,e)
{
console.log('Calculating...(plus separators): '+a+' '+c+' '+e);
console.log('Calculating...(comma separators): ',a,' ',c,' ',e);
console.log('a: ',a);
console.log('c: ',c);
console.log('e: ',e);
return eval(a+c+e);
};
console.log('precise RESULT: ',calculateP(nums[0], nums[1], nums[2]));
Console shows "RESULT: 6" and "precise RESULT: 231".
Which one is correct, if any is? In my opinion the first one ("RESULT 6") is ok, but i'd rather to be sure.
P.S I used eval(), cause originally i will be passing math expression as string "2+3-(4*3)/7" and want it to be calculated. Some kind of simple calculator parser
P.S #2 I used arrays, cause eventually I am going to pass more array elements to this function.
__________________________________________________________________________
EDIT
Is it now correctly used eval()?
function plus(a,b) {
return a+b;
}
function minus(a,b) {
return a-b;
}
var expression = 'minus(plus(2, 3),minus(5,3))';
console.log('(2+3)-(5-3) ',eval(expression));
expression = 'plus(plus(2, 3),minus(5,3))';
console.log('(2+3)+(5-3) ',eval(expression));
I really believe that you can avoid eval nearly everywhere, but if you do something which is bad - do it good!
var expression = '2 + 3 - (4 * 3) / 7';
console.log(eval(expression));
Mathematical operations? Easy!
function cos(input) {
return Math.cos(input);
}
function ln(input) {
return Math.log(input);
}
var expression = '2 + 3 - cos(4 * 3) / ln(7)';
console.log(eval(expression));
What you are doing with eval is absolutely weird and going against eval's nature.
Hi you have to use like below:
var nums = ['2','3','1'], sum = ['+'];
function calculate(nums)
{
var res =0;
for(var i=0;i<nums.length;i++){
res= res+(parseInt(nums[i]));
}
return res;
};
console.log('RESULT: ',calculate(nums))
Just an example how to deal with a string and some values without eval().
var operators = {
'+': function (a, i) {
a[i - 1] += a.splice(i, 2)[1];
return true;
},
'*': function (a, i) {
a[i - 1] *= a.splice(i, 2)[1];
return true;
},
'(': function (a, i) {
var j = i + 1,
b;
while (j < a.length) {
if (a[j] === ')') {
b = a.splice(i + 1, j - i);
b.pop();
a[i] = calculate(b);
return true;
}
if (a[j] === '(') {
return false;
}
j++;
}
},
')': 0
},
precedence = ['(', '*', '+'];
function split(s) {
var a = s.split(''),
i = 1;
while (i < a.length) {
if (!(a[i - 1] in operators || a[i] in operators)) {
a[i - 1] += a.splice(i, 1)[0];
continue;
}
i++;
}
return a.map(function (b) {
return b in operators ? b : Number(b);
});
}
function calculate(a) {
while (a.length > 1) {
precedence.some(function (b) {
return a.some(function (c, i) {
if (b === c) {
return operators[b](a, i);
}
});
});
}
return a[0];
}
document.write(calculate(split('12+23*37')) + '<br>'); // 863
document.write(calculate(split('12+23*(2+(3*4)+5)*37')) + '<br>'); // 16181

Categories