If Else Conditionals within Function in JavaScript - javascript

I'm having issues with conditionals. I want to return the index where pattern starts in string (or -1 if not found). The search is to be case sensitive if the 3rd parameter is true otherwise it is case insensitive.
Examples
index("abAB12","AB",true) returns 2 but index("abAB12","AB",false) returns 0
index("abAB12","BA",true) returns -1 and index("abAB12","BA",false) returns 1
Any idea how I can accomplish this?
This is my code so far
var s = "abAB12"
var p = "AB"
var cs = true
function index(string, pattern, caseSensitive) {
if (pattern) {
var found = false;
if (caseSensitive = false) {
if (string.indexOf(pattern.) >= 0) {
found = true;
}
return (found);
else {
return ("");
}
} else if (caseSensitive = true) {
if (string.toLowerCase().indexOf(pattern.toLowerCase()) >= 0) {
found = true;
}
return (found);
} else {
return ("");
}
}
}
alert(index(s, p, cs));
Fiddle at http://jsfiddle.net/AfDFb/1/

You have some mistype in your code. On the 15th line you have
}
return (found);
else {
This is not not valid. Change it to
return (found);
}
else {
There is another one.
if (caseSensitive = false) {
= used for assignment. You need to use == in if statements when comparing.
Also on the 13th line, there's an extra . after pattern. Remove it.
if (string.indexOf(pattern.) >= 0) {
Your fiddle example

You can use string.search() with a regular expression to accomplish this in one liner:
function index(input, key, caseMatters) {
return input.search(new RegExp(key, caseMatters ? '' : 'i'));
}
Now you can:
index("abAB12","AB",true); // returns 2
index("abAB12","AB",false); // returns 0
index("abAB12","BA",true); // returns -1
index("abAB12","BA",false); // returns 1

You need to use double equals sign == in your if, else statements.
if(caseSensitive == false)
And
if(caseSensitive == true)

You are assigning value inside if condition instead of comparing it.
Try
if (caseSensitive == false) {
and
if(caseSensitive == true)

You'd better use search :
'abAB12'.search(/AB/); // 2
'abAB12'.search(/AB/i); // 0
'abAB12'.search(/BA/); // -1
'abAB12'.search(/BA/i); // 1
The i flag means "case insensitive" ( insensible à la casse :D ).

Related

How to write ternary operator logic for multiple conditions and for optional param?

trying to write logic for my validator functions that has objects we use as errorMap for the input validation , For below logic args.drugName is optional field if user provide text we just want to make sure its greater than 3 letters or in case of empty successCondition should be valid. So for the optional param in typescript how do we fix this issue ?
main.js
{
errorKey: ValidationErrorEnum.InvalidDrugName,
successCondition: (args: DrugPriceParam) => {
let isValid: boolean = false;
isValid = args.drugName.length >= 3 ? true : _.isEmpty(args.drugName) ? true : false;
// if (args.drugName && args.drugName.length >= 3) {
// isValid = true;
// } else if (_.isEmpty(args.drugName)) {
// isValid = true;
// }
return isValid;
}
Error;
error TS2532: Object is possibly 'undefined'.
You could simplify the check to
return !args.drugName || args.drugName.length > 2;
// if empty
// if longer then 2 characters
Its same as you write if condition
(args.drugName && args.drugName.length >= 3) ? true : _.isEmpty(args.drugName) ? true : false;
There is new feature coming in js - optional chaining. you can use this currently using webpack plugin.
https://github.com/tc39/proposal-optional-chaining
Using this we can simply write
args?.drugName?.length >= 3 ? true : _.isEmpty(args.drugName) ? true : false;
Because you're simply returning booleans, you don't actually need to use the ternary operator. You should be able to just pass the result of the comparison operations:
// if (args.drugName && args.drugName.length >= 3) {
// isValid = true;
// } else if (_.isEmpty(args.drugName)) {
// isValid = true;
// }
// Becomes:
isValid = (args.drugName && args.drugName.length >= 3) || _.isEmpty(args.drugName);
Don't forget about short-circuiting, either: If the first half of the || is found to be true, then _.isEmpty won't even be run (and similarly, if the first half of the && is found to be false, then ...length >= 3 won't even be run).

Javascript string in array or a part

I have a Javascript array with multiple values:
var filterClasses = ['col-sm-12', 'hidden-xs', 'hidden-sm', 'hidden-lg', 'hidden-md', 'active', 'btn-'];
I have a function that gets all css classes in the DOM. But i want to check if this class should be added to a new array or not. So i can use indexOf for this:
return filterClasses.indexOf('col-sm-12');
This returns a true, so this class should be ignored.
But now i have a class that is btn-primary. As you see in my array i have the btn- added in it. I want to exclude all classes that contains the word btn-. How can i achieve this?
Current function:
function setupShouldAddClass( cssClass, filterClasses )
{
// If the cssClass exists in the filterClasses then false
if ( filterClasses.indexOf(cssClass) > 0 )
{
return true;
}
filterClasses.forEach(function ( item )
{
if ( stringContains(item, cssClass) )
{
return true;
}
});
return false;
}
function stringContains( needle, haystack )
{
return (haystack.indexOf(needle) !== -1);
}
Maybe you can solve your issue using regular expressions instead of using imperative code:
var classBlackListRegExp = /(col-sm-12|hidden-xs|hidden-sm|hidden-lg|hidden-md|active|^btn-.+)/i;
var result = classBlackListRegExp.test("btn-whatever");
console.log(result);
Check the ^btn-.+ part. This matches anything starting with "btn-".
I believe that your scenario is the ideal use case of regular expressions!
OP concerns if class black list is very large
OP said:
what im wondering is, that if i add more then 100 classes, how does
this handle the line breaks?
You can join the whole array of black-listed strings and create a RegExp object with it as follows:
// I use a templated string and String.prototype.join
// to create a regular expression from a given array:
var classBlackListRegExp = new RegExp(`(${[
'col-sm-12',
'hidden-xs',
'hidden-sm',
'hidden-lg',
'hidden-md',
'active',
'^btn-.+'
].join("|")})`, "i");
var result = classBlackListRegExp.test("btn-whatever");
console.log(result);
You need to use Array#some and check against each value and return true if found.
function setupShouldAddClass(cssClass, filterClasses) {
return filterClasses.indexOf(cssClass) !== -1 || filterClasses.some(function (item) {
return stringContains(item, cssClass);
});
}
I would loop over them like this.
function setupShouldAddClass( cssClass, filterClasses )
{
// If the cssClass exists in the filterClasses then false
var ret = true;
filterClasses.forEach(function(el) {
if (cssClass.indexOf(el) >= 0) {
ret = false;
}
});
return ret;
}
How about bringing the cssClass to what you needed to be compared to:
var transformedToMyNeedsCSS = "btn-primary".replace(/^(btn[-])(?:.*)/,"$1");
// --> Output "bnt-"
And then you compare as you are doing it now:
if ( filterClasses.indexOf(transformedToMyNeedsCSS) > 0 )
{
return true;
}
There's a whole host going wrong here. Let's deal with it step by step:
First
if ( filterClasses.indexOf(cssClass) > 0 )
That is incorrect because indexOf returns -1 if the search term is not found. It returns 0 if it is the first item in the array. So you want >= 0.
Second, the forEach loop:
filterClasses.forEach(function ( item )
{
if ( stringContains(item, cssClass) )
{
return true;
}
});
This achieves nothing. As in, genuinely nothing. Because you are inside a new function (the callback to forEach) return only returns from the inner function. And the return value is then discarded. What this code actually does is loop all the way through the array and do nothing. What you actually want is a clever function called Array.prototype.some. This loops through the array and tests each element. If you return true on any of the elements, some returns true. Otherwise it returns false.
So your code could look like this:
return filterClasses.some(function(element) {
return stringContains(item, cssClass);
}
Now we want to ignore all classes where they begin with btn-. I presume this means that you want to return false if the class begins with btn-.
if (cssClass.indexOf('btn-') === 0) {
return false;
}
So your function now looks like:
function setupShouldAddClass( cssClass, filterClasses )
{
if (cssClass.indexOf('btn-') === 0) {
return false;
}
// If the cssClass exists in the filterClasses then false
if ( filterClasses.indexOf(cssClass) >= 0 )
{
return true;
}
return filterClasses.some(function(element) {
return stringContains(item, cssClass);
});
}

charAt not evaluating

I am trying to write a function that will evaluate equality of characters in a string and return true if 3 in a row match. The charAt() doesn't seem to be working as the if statement always goes to the else block.
function myFunction(num1)
{
var checkNum1;
for (var i = 0; i < num1.length; i++)
{
if (num1.charAt(i) == num1.charAt(i+1) && num1.charAt(i) == num1.charAt(i+2))
{
checkNum1 = true;
break;
}
}
if (checkNum1 == true)
{
return true;
}
else
{
return false;
}
}
What should I be doing to get the last "if" block to return true?
The code that you have provided works fine with strings ie: myFunction("257986555213") returns true.
However, myFunction(257986555213) returns false as expected as charAt is a String method.
As a fail-safe approach, you can try adding the following line to your method at the beginning:
num1 += '';
This should convert your argument to string and you should get your results..
Hope it Helps!!

Javascript - checking whether a condition met in Array forEach

var myStringArray = ["abcd", "efgh", "ijkl"], foundResult = false;
myStringArray.forEach(function(currentString) {
if (/\d+/.test(currentString)) {
console.log("Number found");
foundResult = true;
}
});
if(foundResult === false) {
console.log("Number NOT found");
}
This piece of code is to demonstrate the problem. I have to use an extra variable to check whether there was a match or not. Is there any elegant way to handle this without the variable?
Edit: I know I can use some, but I would like to match the no match case as well as seen in the code's last if condition.
Use some method:
if(["abcd", "efgh", "ijkl"].some(function(i){return /\d+/.test(i)})){
// if matched
} else {
// handle no match
}
An alternative that uses forEach is:
var a = ['abcd', 'efgh', 'ijkl'];
var r;
if (a.forEach(function(a){r = r || /\d/.test(a)}) || r) {
alert('found a number');
} else if (r === false) {
alert('no numbers');
}
but likely any UA that supports forEach will also support some, and some is also probably more efficient as it will stop at the first result of true.

JavaScript Throws Undefined Error

What it is supposed to do -
Example
url1(pages,"ALT") returns "www.xyz.ac.uk"
url1(pages,"xyz") returns ""
The error - TypeError: Cannot call method 'toUpperCase' of undefined
This is just for some coursework, Im stuck with these errors. Any help would be much appreciated
function index(string,pattern,caseSensitive) {
if(caseSensitive == false) {
var v = string.toUpperCase();
} else {
var v = string;
}
return indexNumber = v.indexOf(pattern);
}
var pages = [ "|www.lboro.ac.uk|Loughborough University offers degree programmes and world class research.", "!www.xyz.ac.uk!An alternative University" , "%www%Yet another University"];
alert(url1(pages, "ALT"));
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
if(pages[i].indexOf(seperator)>0){
siteContent = pages[i].split(pages[i].indexOf(seperator));
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
}
}
if(pages[i].indexOf(seperator)>0){
siteContent = pages[i].split(pages[i].indexOf(seperator));
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
If pages[i].indexOf(seperator)<=0, siteContent is still whatever it was from the last iteration. If that happens on the first iteration, siteContent is still [], and siteContent[2] is undefined.
Another problem: the expression pages[i].indexOf(seperator) returns a number, and pages[i].split expects a delimiting string as an argument. Since the number doesn't appear in your input, you'll always get a single-element array, and siteContent[2] will always be undefined. Get rid of .indexOf(seperator), change it to siteContent = pages[i].split(seperator).
One more: get rid of the else { return ""; }. Add a return ""; after the for loop.
Finally, in the first if statement condition, change .indexOf(seperator) > 0 to .indexOf(seperator, 1) !== -1. Since you're getting seperator from the first character of the string, it will be found at 0. You want the second occurrence, so start the search at 1. In addition, .indexOf returns -1 if it doesn't find the substring. You'll need to account for this in both if conditions.
Side note, as this is not causing your problem: never use == false. JS will coerce stuff like 0 and "" to == false. If that's what you want, just use the ! operator, because the expression has nothing to do with the value false.
My final answer is http://jsfiddle.net/QF237/
Right here:
alert(url1(pages, ALT)); // ALT ISN'T DEFINED
I believe you forgot to quote it:
alert(url1(pages, "ALT"));
You should split the string passing the separator character itself. Your function then will look like:
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
console.log(seperator);
if(pages[i].indexOf(seperator)>=0){
siteContent = pages[i].split(seperator); //fixed here
}
console.log(siteContent);
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
}
}
Tell us if it worked, please.
EDIT: It seeems your index() also has a little problem. Please try the function below.
function index(string,pattern,caseSensitive) {
var v;
if(caseSensitive == false) {
v = string.toUpperCase();
pattern = pattern.toUpperCase(); //to clarify: pattern should be uppercased also if caseSensitiveness is false
} else {
v = string;
}
return v.indexOf(pattern);
}
EDIT 2:
And url1() is finally like this:
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
if(pages[i].indexOf(seperator)>=0){
siteContent = pages[i].split(seperator);
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}
}
return "";
}
In this case, the first occurrence of pattern in all pages will be returned.

Categories