I'm taking Colt Steele's Udemy Course titled: "The Web Developer Bootcamp 2020". I have however become stuck on a certain coding exercise. The exercise objective is as follows: Please write a function called lastElement which accepts a single array argument. The function should return the last element of the array(without removing the element). If the array is empty, the function should return null.
I have tried coming up with a solution but cant seem to figure it out. My current best guess is this :
function lastElement (num) {
if (num !== undefined){
return num[num.length -1];
} return null;
}
I'm interested in knowing why the function I have written doesn't work and some pointers on how I should rethink the function, so that it does work.
Best Regards Andreas
Change to this condition.
if (num && num.length>0)
You can use this:
function lastElement(arr) {
if(arr.length>0){
return arr[arr.length-1];
} else{
return null;
}
change your condition to:
if(num && num.length>0)
additionally, if they decide to enter an argument that is not an array,
if(num && Array.isArray(num) && num.length>0)
The problem lies in the difference of truthy and falsy values:
Empty array is truthy but undefined is falsy, so []!==undefined is true, but:
num[num.length -1];
means:
num[-1];
which is undefined .
function lastElement(test) {
if (test.length == 0)
return null;
else
return test[test.length - 1];
}
Related
I know this might be basic and simple but since I am self-learning, so I wanted to know what was wrong and I thought this is the best place to learn from.
I am trying to write a recursive code that returns true or false. The condition to check is if the set of words can make the given target word.
The error I keet getting is :
if (targetString.indexOf(dictionary[i]) == 0) {
^
RangeError: Maximum call stack size exceeded
at String.indexOf (<anonymous>)
I am pretty sure that the problem with code is in a way I am returning because I always find it confusing.
my code is:
let targetString = "furniture";
let dictionary = ["fur", "ure", "nit"];
const tableData = {};
const canConstructRecursive = (targetString, dictionary) => {
if (targetString == "") {
return true
}
for (let i = 0; i < dictionary.length; i++) {
if (targetString.indexOf(dictionary[i]) == 0) {
shorterTargetString = targetString.slice(0, dictionary[i].length);
return canConstructRecursive(shorterTargetString, dictionary);
}
}
return false;
}
console.log(canConstructRecursive(targetString, dictionary));
I am learning recursion and from time to time I feel I don't understand the logic of return to next/previous recursive call.
I would really appreciate it if someone could help me with what I am doing wrong and change my way of thinking.
My way of thinking is that:
the base case is returned if it is reached at that stage otherwise loop go through all the option and the inner node or upper stack need to return value to lower stack so I am doing return canConstructRecursive() inside for. If even in all options which is all iteration of for loop, it is not returned, there is return false at the end.
Thank you in advance
The reason is that although your variable is named shorterTargetString, it is not guaranteed to be really shorter. If i is the index of the shortest word in dictionary, then there is no way your string will ever get shorter by recursing with it.
The mistake is that the slice should not start at 0, but after the part that was matched, so remove the first argument from the slice call.
This will solve the stack overflow error.
Secondly, if the recursive call returns false you should not give up, but keep trying with the next word. So only return out of the loop when you got true from recursion:
let targetString = "furniture";
let dictionary = ["fur", "ure", "nit"];
const tableData = {};
const canConstructRecursive = (targetString, dictionary) => {
if (targetString == "") {
return true
}
for (let i = 0; i < dictionary.length; i++) {
if (targetString.indexOf(dictionary[i]) == 0) {
shorterTargetString = targetString.slice(dictionary[i].length);
if (canConstructRecursive(shorterTargetString, dictionary)) {
return true;
};
}
}
return false;
}
console.log(canConstructRecursive(targetString, dictionary));
More on the second fix.
Your code will unconditionally return the value of the recursive call, even when it is false. This is not good: in case the recursive call returns false, the caller should continue with its for loop to try alternatives.
Let's for instance add a word to your example dictionary: you'll agree that adding a dictionary word should not change the outcome for the input "furniture". So here it is:
["furn", "fur", "ure", "nit"]
But surprise: your code now returns false for "furniture"! This is because "furn" mathes, but the recursive call with "iture" as first argument does not find further matches, so it returns false, and now the caller also returns false. This is wrong. It should give up on "furn", but not on the whole exercise. It should have continued and tried with "fur". This is why the exit out of the for loop should only happen upon success, not upon failure. Failure can only be confirmed when all dictionary words have been tried, so the for loop must continue for as long as there is no recursive success.
User trincot already explained what was wrong with your code. Here, I just want to point out that your structure, which is something like for (...) {if (...) { if (...) {return true} } } return false, might be better handled with Array.prototype.some and an && statement. Combining this with the fact that t .indexOf (s) == 0 might more clearly be expressed as t .startsWith (s), and sprinkling in a conditional statement instead of an if statement, we can arrive at what I think is a more elegant formulation:
const canConstruct = (t = '', ss = []) =>
t == ''
? true
: ss .some ((s) => t .startsWith (s) && canConstruct (t .slice (s .length), ss))
console .log (canConstruct ('furniture', ['fur', 'ure', 'nit'])) //=> true
console .log (canConstruct ('furniture', ['furn', 'fur', 'ure', 'nit'])) //=> true
console .log (canConstruct ('banana', ['b', 'ana'])) //=> false
console .log (canConstruct ('banana', ['ba', 'na'])) //=> true
I am pretty new at this stuff, and I am solving a series of questions, but I've got lost in this one.
I have to verify if a number can be divided by other, and the answer must be true or false.
I got his
function solucao(numero, x) {
solucao(numero % x);
if (solucao === 0) {
resultado = true;
}else{
resultado = false;
}
}
But I'm getting runtime error and can't see whats is missing.
So you want to check if a number numero is divisible by x. The modulo operator can help. Try this:
function solucao(numero, x){
if (numero % x == 0){
return true
}
else {
return false
}
}
function solucao(numero, x) {
let resultado;
if (numero % x === 0) {
resultado = true;
}else{
resultado = false;
}
return resultado;
}
I think you get confused at some point. You are calling the function, inside of itself. You should do like this, and also, declare the result variable.
I am sure this will help:
function checkIfDivided(){
// in this section the variables come from an html document
var number=parseInt(document.getElementById("number").value);
var divisor=parseInt(document.getElementById("divisor").value);
if(number%divisor==0)
return true;
else return false;
}
or
function checkIfDivided(number,divisor){
//in the function the variable are given as parameters
if(number%divisor==0)
return true;
else return false;
}
Looks like two things to me:
You haven't declared your 'resultado' variable ( this can be as simple as just typing 'let resultado;' without the single quotes
You haven't returned your 'resultado' variable after the if/else statement
Right now, your function is using an undeclared variable and not returning anything, so that is why you are getting an error. Fix the two above steps and you should be good! :)
You clearly understand that the modulus operator is the way to go. Using it we discover that 12 is divisible by 3 because 12 % 3 return zero. Zero is considered a "falsy" value while any other number is considered "truthy".
Given this then if 12 % 3 returns a "falsey" value (zero) we can't use the result directly. But what if we can "flip" false to true? We can, using the not operator (!).
Using the ! operator on the result of a math problem requires the use of parentheses around the math problem itself.
So the problem in code becomes (12 % 3) and to 'flip' it with the ! operator it becomes
!(12 % 3).
This is proven below with:
console.log(!(12 % 3)) --> logs true
console.log(!(12 % 5)) --> logs false
The function implementation of that is simple and also proven:
console.log(isDivisible(12,3)); --> logs true
console.log(isDivisible(12,5)); --> logs false
console.log(!(12 % 3))
console.log(!(12 % 5))
function isDivisible(number, x){
return !(number % x);
}
console.log(isDivisible(12,3));
console.log(isDivisible(12,5));
There is one other way to do so and i think its much cleaner.
console.log(Number.isInteger(10/2)) //true
console.log(Number.isInteger(4/2)) // false
//a must be greater than b
function check(a,b) {
console.log(Number.isInteger(a/b))
return Number.isInteger(a/b)
}
check(10,5)//true
check(8,3)//false
This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 4 years ago.
I'm using Javascript to find if something is in an array or not, but when I'm using this code it doesn't alert anything at all, which means it's not working correctly. What am I doing wrong?
var theArray = new Array("one","two","three");
if (theArray.indexOf("one")) { alert("Found it!"); }
if (!theArray.indexOf("four")) { alert("Did not find it!"); }
you should use the includes function as:
if (theArray.includes('one')) { alert("Found it!"); }
Remember that the starting index of an array is 0.
From the docs.
The indexOf() method returns the first index at which a given element
can be found in the array, or -1 if it is not present.
The index of one is 0, which is falsy so the first check will fail. indexOf will return -1 if there is no match so you should explicitly check for that.
var theArray = new Array("one","two","three");
if (theArray.indexOf("one") !== -1) { alert("Found it!"); }
if (theArray.indexOf("four") === -1) { alert("Did not find it!"); }
That's because indexOf returns a number which is the index of the matched string, and -1 if the string does not exist in the array. You need to compare the return value to numbers like these:
if (thisArray.indexOf('one') > -1) { alert('Found it!') }
if (thisArray.indexOf('four') > -1) { alert('Did not find it') }
You can use includes to return a boolean instead, if you'd like.
if (thisArray.includes('one')) { alert('Found it!') }
You'd think that might work, wouldn't you? But there are two gotchas here.
.indexOf() returns the index of the first matching element it finds, or -1 if it doesn't find anything. And remember that JavaScript array's are zero-indexed, meaning the first array element has the index of zero. So if the match is the first element, then zero is the returned value, and like most languages, zero means false when you'd want it to be true. However this bring us to point #2.
.indexOf() performs a comparison using strict equality, or in other words ===. The returned value won't be coerced like if you used true == 1. This is highly relevant here because if it didn't use strict equality, then any element it found (other than the first) would have an index of one or higher, and then your comparison would succeed. For example if (theArray.indexOf("two")) would work since the index of that element is 1. However, single indexOf() does a strict equality check, it fails. Which is why you need to explicitly compare the returned value of indexOf() to something, normally > -1.
Linear search. It is a 'language agnostic' approach to solving the problem of searching an unordered list. Yes, you can use array.includes(), which is a neat one-linear specific to JavaScript. But, it appears as through you are new to programming, at least with JavaScript, and before you take advantage of some of those fancy tools that make life easier, it's worth implementing them yourself so you truly understand what's going on under the hood and more importantly, why it works.
function contains(array, value) {
// Loop through the entire array
for (let i = 0; i < array.length; i++) {
// Return true on first match
if (array[i] === value)
return true
}
// Return false on no match
return false
}
// Make an array
let a = ['one', 'two', 'three']
// If it has an element, notify
if (contains(a, 'one'))
alert('found it')
You could use the bitwise NOT ~ operator and check the value of the returned index or -1 if not found.
~ is a bitwise not operator. It is perfect for use with indexOf(), because indexOf returns if found the index 0 ... n and if not -1:
value ~value boolean
-1 => 0 => false
0 => -1 => true
1 => -2 => true
2 => -3 => true
and so on
var theArray = new Array("one", "two", "three");
if (~theArray.indexOf("one")) {
console.log("Found it!");
}
if (!~theArray.indexOf("four")) {
console.log("Did not find it!");
}
I'm following an online course about Javascript Functional Programming
at the Exercise 16 it show you how reduce is actually implemented, in order to help you understand how to use it, but into this implementation there is something i don't actually get, i'll show the code:
Array.prototype.reduce = function(combiner, initialValue) {
var counter, accumulatedValue;
// If the array is empty, do nothing
if (this.length === 0) {
return this;
}
else {
// If the user didn't pass an initial value, use the first item.
if (arguments.length === 1) {
counter = 1;
accumulatedValue = this[0];
}
else if (arguments.length >= 2) {
counter = 0;
accumulatedValue = initialValue;
}
else {
throw "Invalid arguments.";
}
// Loop through the array, feeding the current value and the result of
// the previous computation back into the combiner function until
// we've exhausted the entire array and are left with only one value.
while(counter < this.length) {
accumulatedValue = combiner(accumulatedValue, this[counter])
counter++;
}
return [accumulatedValue];
}
};
I don't understand the first if statement, when it check for this.length what this actually mean?
Take note this is different from the reduce in ES5, which returns an value instead of an Array, this is used just as a sample for the learning purpose.
Array.prototype.reduce = function(...
is saying, "create a function on the prototype of Array" - this means that the new reduce function will be callable on all arrays, eg:
[1, 2, 3].reduce(...
This means you can also call it on empty arrays, eg:
[].reduce(...
Building on the comment:
If the array is empty, do nothing
You're working on an array, and when the function is called, this is set to the array that reduce was called on. This implementation of reduce assumes that if that array is empty (ie this.length === 0), you can't logically reduce it any further - there's nothing to reduce, so you can return the same empty array.
As pointed out by #Alnitak in the comments, this implementation of reduce is flawed as compared to the specification. A different implementation is available on the MDN for polyfilling older browsers.
I have a piece of code that tests for the existence of a variable, using an if statement like the example below. I need to do one thing if the var is set, a different thing if its not. In a certain test case, the var needed to be set to 0, but that is the same is having an unset var in JS, apparently:
var toMatch;
toMatch = 0;
if (!toMatch) {
document.write("no");
} else {
document.write(toMatch);
}
// html is "no"
jsFiddle
So my problem is, how do I test for a var if its value is legitimately zero. I should point out, that in my function possible values to be passed are 0-40+.
In the past I've used a work around like setting the initial value to a number high enough that it is not likely to be passed to the function but that seems hackey to me. Is there a better way to do it?
var toMatch;
toMatch = 0;
if (toMatch === 0) { // or !== if you're checking for not zero
document.write("no");
} else {
document.write(toMatch);
}
toMatch === 0 will check for zero.
toMatch === undefined will check for undefined
the triple equals are strict comparison operators for this sort of scenario. See this blessed question: Difference between == and === in JavaScript
Instead of
if (toMatch)
use
if (toMatch == null)
You can see if a name is undefined with:
if (typeof bad_name === "undefined") {
Javascript is a bit funny when it comes to values and boolean checks. I suggest reading about Truthy and Falsey in Javascript.
You should use the identity inequality operator !==:
var toMatch;
toMatch = 0;
if (toMatch !== 0) {
document.write("no");
} else {
document.write(toMatch);
}
It is also worth understanding the differences between == and ===.