Comparison operators !== against 0 - javascript

I think that it is obvious what my code does.
Why does my code return a whole string if I use the !== operator? I know that arrays in Javascript start from at index 0, and here I'm entering the whole filename as the argument, so indexOf(".") will always be greater then 0. No, I'm not passing an .htaccess file here.
function getFileExtension(i) {
// return the file extension (with no period) if it has one, otherwise false
if(i.indexOf(".") !== 0) { //
return i.slice(i.indexOf(".") + 1, i.length);
} else {
return false;
}
}
// here we go! Given a filename in a string (like 'test.jpg'),
getFileExtension('pictureofmepdf'); return given string
// both operand are same type and value
But if I change comparasion to
(i.indexOf(".") > 0) // logs false
P.S. I case that you are asking, this is form usvsth3m.

indexOf() returns the index of the substring, so it can return 0, which would mean that the substring appears at position 0. If the substring is not found, it returns -1 instead, so change your if statement to reflect this logic:
if(i.indexOf(".") >= 0)
Additionally, you should use substring() to extract a substring from a string - slice() is for arrays.
return i.substring(i.indexOf(".") + 1, i.length);
Still, I think a better way to do this is with split():
var fileNameArray = i.split("."); // "foo.txt" --> ["foo" "txt"]
if(fileNameArray.length >= 2) {
return fileNameArray[1];
} else {
return false; //maybe you want to return "" instead?
}

The String method indexOf returns (if it is founded) the first index of the string you search, and remember, index can be zero, that why you have to do a strict comparision to check if indexOf it is not returning a boolean false.
I will suggest you to use lastIndexOf for this case because a file named as something.min.js will return min.js as an valid extension, and nope.

Well, to simplify, I omit that indexOf returns index which is typeof number, or -1, not returning boolean value FALSE in case when given value not found. So in case of comparing -1 to 0, result is true, and that's why I actually geting outputed given string, instead false. Well, MDN is in my bookmark bar now
var z = -1;
console.log(z >= 0); // evaluates false because -1 < 0
console.log(z !== 0); // evaluates true because -1 !== 0
// also if z > 0 it is !== 0, but could be < 0
So next code works like a charm.
function getFileExtension(i) {
// i will be a string, but it may not have a file extension.
// return the file extension (with no period) if it has one, otherwise false
if(i.indexOf(".") >= 0) {
return i.substring(i.indexOf(".") + 1, i.length);
} else {
return false;
}
}
getFileExtension('pictureofmepdf');

Related

Problem recursively looping through characters in a string to solve Palindrome problem

I am attempting to solve a generic Palindrome problem recursively. However, it seems that my algorithm is only evaluating the first recursive call, not the second, which should check all characters in the string. There is apparently a logic error in my algorithm, but I can't spot it. Can anyone advise? See the code below.
function isPalindrome(totalChars: number, lastIdx: number, str: string): boolean | undefined {
console.log(`lastIdx: ${lastIdx}; char: ${str[lastIdx]}`);
// const curIdx = lastIdx;
let highIdx = lastIdx;
const lowIdx = totalChars-1 - highIdx;
// Base Case:
if(totalChars === 0) return true;
if (lowIdx === highIdx) return true;
if (lowIdx > highIdx) {
console.log(`Endpoint reached; STR: ${str}; LOW: ${str[lowIdx]}; high: ${str[highIdx]}`);
return;
}
if(str[lowIdx] === str[highIdx]) {
console.log(`Loop through idx; STR: ${str}; LOW: ${str[lowIdx]}; high: ${str[highIdx]}`);
return true;
}
else if(str[lowIdx] !== str[highIdx]) return false;
// Recursive Case:
return isPalindrome(totalChars, highIdx, str) && isPalindrome(totalChars, highIdx-1, str);
}
// console.log("a is Palindrome: " + isPalindrome("a".length, "a".length-1, "a"));
// console.log("motor is Palindrome: " + isPalindrome("motor".length, "motor".length-1,"motor"));
console.log("rotor is Palindrome: " + isPalindrome("rotor".length, "rotor".length-1,"rotor"));
There are a few problems:
your if...else will always result in a return, and so the statement with the recursive call will never be executed.
Note that the condition after else if will always be true when it gets evaluated, since it is the negation of the condition that is evaluated in the earlier if statement.
More importantly, when that earlier if condition is true, you don't want to return, as it has not been verified yet that the remaining (inner) characters match. This still has to be verified via the recursive call, so this is not a place to perform a return. Just remove that if block, and only return when the characters differ.
So replace this:
if(str[lowIdx] === str[highIdx])
{
return true;
}
else if(str[lowIdx] !== str[highIdx]) return false;
With just:
if(str[lowIdx] !== str[highIdx]) return false;
The first recursive call passes the same arguments as the current execution of the function got -- this will lead to infinite recursion. A recursive call must always make the problem smaller. In this case, there is actually no need to make two recursive calls, and you should remove that first one.
So replace this:
return isPalindrome(totalChars, highIdx, str) && isPalindrome(totalChars, highIdx-1, str);
with:
return isPalindrome(totalChars, highIdx-1, str);
The base case has a condition where return is executed without boolean return value. The function should always return a boolean value. In this case it should be true, because it means that all character-pairs were compared, and there is no single-middle character remaining (the size of the string is even). So you can combine this case with the previous base case. In fact, that base case condition will also work when totalChars is zero, so you can omit that first if.
So change this:
if (totalChars === 0) return true;
if (lowIdx === highIdx) return true;
if (lowIdx > highIdx) {
return;
}
with:
if (lowIdx >= highIdx) return true;

Finding if something is in an array or not in javascript [duplicate]

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!");
}

Why do I get a different output when using an if statement in filter as oppose to just return

I am new to JavaScript and I am learning a little about High Order Functions. I was wondering if someone can tell me why:
function filter_list(arr) {
return arr.filter(function(item) {
return typeof(item) == 'number';
});
}
// input = [1,'a','b',0,15] output = [1,0,15]
But
function filter_list(l) {
return l.filter(function(item){
if (typeof item == "number") {
return item;
}
});
}
// input = [1,'a','b',0,15] output = [1,15]
I am having a hard time seeing the difference.
Filter
Filter returns a value if a condition is true and ignores it if it is false
function filter(arr) {
return arr.filter(function(x) {
return x
})
}
const booleans = [false, false, true]
// this logs only "true"
console.log(filter(booleans))
Truthy and Falsy
Additional to true and false there is truthy and falsy. This means that values evaluat to true or false in condition statements. You can read more on mdn
function getBooleanValue(value) {
return !!value
}
console.log('1 gets cast to:', getBooleanValue(1))
console.log('0 gets cast to:', getBooleanValue(0))
Your Code
The second code snippet didn't returns the 0 because it gets cast to false. To get the expected array you have to change the return value from item to true
function filter_list(l) {
return l.filter(function(item) {
if (typeof item == "number") {
return true;
}
return false
});
}
console.log(filter_list([1, 'a', 'b', 0, 15]))
This is the 'beauty' of javascript. At your first example you return a boolean in your filter. the type of item is equal to number or it isn't
In the second example you return the item itself. So you return 1, 0 and 15. Because 1 is true and 0 is false in programming, javascript sees the returning 0 as a filter failure. So it is filtered. In other words, everything different from 0 is true, and 0 is false.
In the second case:
function filter_list(l) {
return l.filter(function(item){
if (typeof item == "number") {
return item;
}
});
}
item 's value is used to filter or not itself. When item is worth 0, it's equivalent to false therefore, it's not included in the result. The function passed to filter expects a boolean result, if you do not return a boolean, you have to understand how javascript will interprete it.
Check it by yourself, 0 is equivalent false, therefore, if you return 0, the element is going to be filtered:
console.log(false == 0)
Filter checks for Boolean values, it will take 0 and 1 as true and false, so if false == 0, the return 0 wont work.
console.log(filter_list([1,'a','b',0,15]));
function filter_list(l) {
return l.filter(function(item){
if (typeof item == "number") {
return item;
}
});
}
This is because JavaScript has falsy values. Javascript takes null, undefined, 0 & false as falsy.
function filter_list(arr) {
return arr.filter(function(item) {
return typeof(item) == 'number';
});
}
// input = [1,'a','b',0,15] output = [1,0,15]
in this function you return boolean after comparing type, in which case each item that returns true in comparison is selected.
while in this function you are returning values instead of result of comparison, since 0 is falsy value it doesn't get selected for your filtered list.
function filter_list(l) {
return l.filter(function(item){
if (typeof item == "number") {
return item;
}
});
}
// input = [1,'a','b',0,15] output = [1,15]
Filter expects you to provide a boolean variable. This is done in your first example. The second example is just possible because Javascript is not using static types. The item 0 interpreted as boolean is false. So if you do return 0, filter does not append the item.
The two examples you have provided are not at all equivalent.
In the first example you are returning the result of evaluating the expression typeof(item) == 'number' which will either be true or false depending.
In the second you have three fairly different possibilities.
The first two are covered by the if statement: if the type of the item is number you are returning the item itself which may be 'falsey' (zero or NaN) and thus fail the filter or 'truthy' (anything but zero or NaN).
But there's also an implicit return of undefined if the type of item is not number. This doesn't have an impact in a filter because undefined is falsey, but you will likely get unexpected results using copying this pattern to use elsewhere and it should be avoided.
It's because the Array.prototype.filter() creates a new array with all elements for which the test function returns a truthy value (see here: Understanding JavaScript Truthy and Falsy)
And because 0 is falsy it's not part of the returned array in the second sample.

Bitwise AND operations in Javascript

I make a project that reads value from a remote JSON. In this project the remote JSON can give me with one variable 16 different types of alarm. The implementation is by a bynary 16bit value expressed in int. So if there is the third alarm it should return me 8 (bynary 1000) and if the second,eigth and tenth alarm is up it return me 1284 (binary 10100000100). Well when there is no alarm it returns me 0.
So, I create a function in JS (accordly to here) that passing the value returned (8/1284/0 in the example) returns me a simple true or false if there is an alarm. The function is pretty simple:
function IsOnAlarm(passedVal) {
if (passedVal & 0) {
return false;
} else {
return true;
}
}
but it does not function :-(
I create a JSFiddle that shows the problem. How can I solve it? Thanks in advance.
Well as far as I understand you just need to check whether the value is 0. There's no need for any bitwise operation.
function IsOnAlarm(passedVal) {
return passedVal != 0;
}
Side note: passedVal & 0 is always 0 no matter what passedVal is (that's why it always goes to else).
You can do it like
function IsOnAlarm(passedVal) {
if (passedVal != 0) {
return false;
} else {
return true;
}
}
Check this http://jsfiddle.net/KQH43/3/
The AND operator always return false if one of the operands is zero, see below:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
The easiest way to rewrite your function is as follows:
function IsOnAlarm(passedVal) {
return !!passedVal;
}
Explanation: the double negation operation (!!) allows you to cast the input to boolean. Any non-zero value will evaluate to true, zero evaluates to false.
Check this jsfiddle, it is using bitwise AND comparison.
I've modified your function to make it easier to understand:
function AreAlarmsOn(alarmsToCheck, alarmState) {
return and(alarmsToCheck, alarmState)!=0;
}
It takes alarmsToCheck and checks its bits against alarmState bits, alarmsToCheck can have bits for several alarms if you need to check multiple alarms.
Is this what you're looking for?
var getFlags = function(val) {
var results = [];
for (var i = 0; i < 16; i++) {
results.push(!!((val >> i) & 1));
}
return results;
};
var flags = getFlags(1284);
flags[2] //=> true
flags[8] //=> true
flags[10] //=> true
// all other values ==> false / undefined

How to make 0 return true?

I have a situation where I am searching for something in an array, and if a value is found, I do something. I am doing this by setting a variable to undefined, and then when the value is found, setting to the index of the element found. This would work if the value returned is anything but 0, but if it is 0, then it returns as false. How can I work around this?
var index = undefined;
for(var i=0; i<ARRAY; i++)
{
if(CONDITION)
index = i;
}
if(index)
{
DO SOMETHING
}
So my problem occurred when the index turned out to be zero, because this returned false. The reason I want to do it this way is because I am not sure if it exists in the array or not.
How about testing the result to see whether it's >= 0 instead of relying on its truthyness?
if (index >= 0) { ... }
The undefined value is not >= 0 so that should work.
Why not be 100% explicit? This is, after all, what you're actually intending to check:
if (typeof index === 'number')
{
// DO SOMETHING
}
I prefer this even to checking >= 0 since that operator gives some weird results for non-numeric values:
Input | >= 0
------------
"1" | true
false | true
null | true
[] | true
"" | true
(See this jsFiddle for evidence.)
You mean you have a variable that may be undefined or some number, and you want undefined to be distinguishable from 0?
Then:
if (index) // wrong
if (index >= 0) // right
Or you can use type-aware comparisons:
if (index !== undefined) { .. }
You can use -1 to indicate the index was not found in the array. As you mentioned, 0 will be implicitly cast to a "false" if you use it like a boolean. You can use === to avoid an implicit cast.
You could... not do it like that, because you need to work within JS's definition of truthiness, or check explicitly for undefined.
0 is falsey in javascript; use === to test whether a value is actually false:
foo = 0;
foo == false //true
foo === false //false
As you're setting the value to undefined one way of testing is to see whether the value is Not a Number:
if (!isNaN(foo))
{
//foo is numeric
}
I wrote these simple utility functions to help with more math-oriented tasks:
function isFalsy(val) {
return (((!val)&&(val!==0))||(val === null)||(val === NaN)||(val === ""))
}
function isTruthy(val) {
return !isFalsy(val)
}

Categories