How To Break Out Of arr.find()? - javascript

This might not be best practice, but I was wondering if it's possible to break from the arr.find() method.
Here's some code that I was working on that I've since redone with a loop but I was wondering why this is not allowed?
Any help is appreciated!
I understand this isn't the best approach to the problem at hand I'm just curious to why the break doesn't work as intended where am I messed up in my thinking?
//Using the JavaScript language, have the function SimpleSymbols(str) take the str parameterbeing passed and determine if it is an acceptable sequence by either return in the string true or false. The str parameter will be composed of + and = symbols with several letters between them (ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter.
//loop through Array
//Determine if letter is surrounded by +
//If yes continue on and return true
//If no break loop and return false
function SimpleSymbols(str){
str = str.split('');
var pass = null;
function finder(char){
if (char.length === 1 && char.match(/[a-z]/i)){
var firstPlus = str.indexOf(char)- 1;
var secondPlus = str.indexOf(char)+ 1;
console.log(str[firstPlus]);
if (str[firstPlus] === '+' && str[secondPlus] === '+'){
pass = 'true';
} else {
pass = 'false'
break;
}
}
}
str.find(finder);
return pass
}
SimpleSymbols('++d+===+c++==a++q++');

This code will break loop in your case after 5 iterations:
SimpleSymbols('++-+d+===*c+3++==a++q-3++');
function SimpleSymbols(str){
str = str.split('');
var pass = null;
str.find(finder);
function finder(char, i){
console.log('Iteration No.' + i);
if (str.indexOf(char) && char.length === 1 && char.match(/[a-z]/i)){
var firstPlus = str.indexOf(char)- 1;
var secondPlus = str.indexOf(char)+ 1;
//console.log(str[firstPlus]);
if (str[firstPlus] === '+' && str[secondPlus] === '+'){
pass = 'true';
return pass;
} else {
pass = 'false';
}
}
}
console.log('FINAL RESULT = ' + pass);
return pass;
}

Related

getting undefined from a function

Hello Write a function to convert a name into initials. This kata strictly takes two words with one space in between them.
this is my code.
function abbrevName(name) {
var first;
var last;
var new1 = name.split("")
for (var i = 0; i < new1.length; i++) {
if (new1[i] == new1.toUpperCase) {
first = new1[i]
if (new1[i] == new1.toUppercase && first == defined) {
last = new1[i]
}
return first + "." + last;
}
}
/enter code here
}
abbrevName("Faris Abutaya")
i am getting undefined help me please
You're getting undefined from your function because you need to return something from it.
Try adding a return statement near the bottom and you'll get an output. What you actually need to return I'll leave up to you.
function abbrevName(name) {
var first;
var last;
var new1 = name.split('');
for (var i = 0; i < new1.length; i++) {
if (new1[i] == new1.toUpperCase) {
first = new1[i];
if (new1[i] == new1.toUppercase && first == defined) {
last = new1[i];
}
return first + '.' + last;
}
}
return new1;
}
abbrevName('Faris Abutaya');
Some problems with your code are noted in comments here:
function abbrevName(name) {
var first;
var last;
var new1 = name.split("")
for (var i = 0; i < new1.length; i++) {
if (new1[i] == new1.toUpperCase) {
first = new1[i]
// toUpperCase needs `()` to be called; new1 holds the array, not a letter; `== defined` is invalid
if (new1[i] == new1.toUppercase && first == defined) {
last = new1[i] // this statement will run as soon as first is found (so last = 'F')
}
return first + "." + last; // return happens as soon as first `if` condition is true
}
}
}
abbrevName("Faris Abutaya")
Here is revised code. Note that console.log statements help to debug because we can see what each variable holds at various points in the script. (To see your browser console, use f12 or ctrl+shift+i)
function abbrevName(name) {
const letters = name.split(""); // Renamed new1 to letters
let first ="", last = "";
let firstFound = false, lastFound = false; // New variables
console.log(letters);
for (let i = 0; i < letters.length; i++) {
console.log(letters[i]);
if(letters[i] == letters[i].toUpperCase()){ //Compare letter to letter, not letter to array
if(firstFound == false){
firstFound = true; // Now we have a way to know last is coming
first = letters[i];
console.log("first: " + first);
}
else{ // firstFound is not false
lastFound = true
last = letters[i];
console.log("last: " + last);
}
}
}
return first + "." + last; // return statement moved out of for loop
}
console.log(abbrevName("Faris Abutaya"));
There are many mistake in the written code.
toUppercase is a function and it should be called as a method of the string. Therefore the code inside the first if statement would never run. For example:
console.log( "h".toUppercase );
//H
new1 is an array of characters and you should call toUpperCase for each character not the whole array.
3.You should also check whether first is defined or not.
function abbrevName(name) {
var first;
var last;
var new1 = name.split("");
for (var i = 0; i < new1.length; i++) {
if (new1[i] === new1[i].toUpperCase() && new1[i] != " ") {
if(first == undefined){
first = new1[i];
}else if (new1[i] == new1[i].toUpperCase() && first != undefined){
last = new1[i];
return first + "." + last ;
}
}
}
}
abbrevName("Faris Abutaya")
//F.A
-It would be so much nicer to do it with RegEx. Because the code you wrote will just work in the times which user enters some names containing just 2 words and capitalizes first letters.

Comparing a reversed string to it's original without using .reverse() method

I'm attempting to compare an original string argument with its reverse. In essence, this function is supposed to verify whether or not a given string is a palindrome. Key points:
String needs to be converted to all lowercase, which I did.
String needs to consist of only alphanumeric characters, which I did.
When compared, the original string and formatted string must match. If they do, the boolean value of true gets returned, otherwise false does.
Here is the source code: JS Fiddle | Alternatively, code is below:
function palindrome(str) {
var reverseString;
var temp;
var formatted;
// make sure input gets converted to lowercase
temp = str.toLowerCase();
// make sure all non-alphanumeric characters get removed
// once converted to lowercase, ensure that all special characters and digits are stripped from the string
formatted = temp.replace(/[^A-Za-z]/g, '');
// now we need to compare two strings: the raw input vs the string in reverse
for (i = formatted.length -1; i >= 0; i--) {
reverseString += formatted[i];
}
if (reverseString === str) {
return true;
}
return false;
}
palindrome("123$EYE");
function palindrome(str) {
var reverseString=""; // initialize every string to ""
var temp="";
var formatted="";
temp = str.toLowerCase();
formatted = temp.replace(/[^A-Za-z0-9]/g, ''); // I added 0-9 in your regex to have numbers in your string
for (i = formatted.length -1; i >= 0; i--) {
reverseString += formatted[i];
}
if (reverseString === formatted) { // change str to formatted
return true;
}
return false;
}
var isPal = palindrome("123$EYE");
alert(isPal); // try it on `alert` if it is true or false
Your code is ok. But you have some flaws. You should initialize your String to "" so it will not have a value of undefined. The one you put on your if statement is str which is your original String word, you should put your formatted String because that is the one you removed the special characters.
Why reverse and compare? You just need to compare the characters of the same position from the head and from the tail. First str[0] and str[length - 1], then str[1] and str[length - 2], and so on. Till you reach the middle, or any comparison fails.
function isPalindrome(str) {
var len = str.length
for (var i = 0; i < Math.ceil(len/2); i++) {
if (str[i] !== str[len - 1 - i]) {
// or add more comparison rules here
return false
}
}
return true
}
isPalindrome('1') // true
isPalindrome('121') // true
isPalindrome('1221') // true
isPalindrome('1211') // false
alphanumeric characters?
function palindrome(str) {
var temp;
temp = str.toLowerCase();
temp = temp.replace(/[^A-Za-z0-9]/g, '');
console.log(temp);
for (let a = 0, b = temp.length - 1; b > a; a++, b--) {
if (temp.charAt(a) !== temp.charAt(b))
return false;
}
return true;
}
You didn't initialize reverseString so it will be undefined at the beginning. Adding a character 'a' to undefined returns a string 'undefineda', instead of 'a' which you probably expect.
Change your code to
var reverseString = '';
and it'll work
Here is an elegant way to reverse the text:
var rev = temp.split('').reverse().join(''); // reverse
check out fiddle:
function palindrome(str)
{
var temp = str.toLowerCase() // converted to lowercase
.replace(/[^A-Za-z]/g, ''); // non-alphanumeric characters removed
var rev = temp.split('').reverse().join(''); // reverse
console.log(temp, ' === ', rev, ' is ', temp === rev);
if(temp === rev)
{
return true;
}
return false;
}
var out = palindrome("123$EYE");
document.getElementById('divOutput').innerHTML = out;
<div id="divOutput"></div>

Javascript Palindrome Check

I have to write a script to check if a word entered by a user is a Palindrome. I've gotten as far as validating the word and displaying the number of characters. Also not supposed to use the reverse method.
I've looked at some of the examples here and think I need to turn the user input into a string and use a "for" loop and if/else statement. But how do I turn the user input into a string in order to check each character? This is a total mess but it's all I've got so far:
function checkWord(userWord3) {
var answer = "Your word is";
answer += retrieveWord(userWord3);
return (answer);
}
function retrieveWord(userWord) {
var string = userWord;
var i = userWord.length;
for(var i = 0; i < str.length / 2; i++) {
alert(str[i], str[str.length -i -1]);
if( str[i] != str[str.length - i -1] ) {
return false;
}
}
}
You can try this function
function isPalindrome(str){
if(str.length < 2) return true;
if(str[0] != str.slice(-1)) return false;
return isPalindrome(str.slice(1,-1));
}
It uses recursion and its logic is as follows
The empty and 1 character string are considered palindromes
if(str.length == 0 || str.length == 1) return true;
if the first and last characters are not the same the word is not a palindrome
if(str[0] != str.slice(-1)) return false;
if the first and last are the same continue searching in the remaining string
return isPalindrome(str.slice(1,-1));
var result = document.querySelector(".result");
var palindrome = "<span class='palindrome'>it is a palindrome</span>";
var notpalindrome = "<span class='notpalindrome'>it is NOT a palindrome</span>";
function isPalindrome(str){
if(str.length == 0 || str.length == 1) return true;
if(str[0] != str.slice(-1)) return false;
return isPalindrome(str.slice(1,-1));
}
document.querySelector("input").addEventListener("keyup", function(){
if(isPalindrome(this.value)){
result.innerHTML = palindrome;
} else {
result.innerHTML = notpalindrome;
}
})
.palindrome{color: green;}
.notpalindrome{color: red;}
<input type="text" />
<span class="result"></span>
How are you collecting the user input? In just about every case, it will come into the program as a string (i.e. textbox, prompt), so you don't have to worry about converting it into one.
This code simply takes the word, breaks it into an array, reverses the array and then compares that reversal against the original word. It works for me:
function test(input){
var originalData = input;
var a = [];
for(var i = 0; i < input.length; ++i){
a.push(input.charAt(i));
}
a.reverse();
return (a.join('') === originalData) ? true : false;
}
var word = document.getElementById("userWord");
alert(test(word));
See working version at: https://jsfiddle.net/6cett0bc/6/
The most basic version I can think of is to split the word into letters and check the first against the last, until you end up in the middle, where it doesn't matter if there is an odd amount of letters.
UPDATE I've tested the performance of various implementations and changed my array based answer to a pure string based solution.
If you're curious, here are the performance benchmarks
The fastest solution (so far):
function palindrome(word) {
var middle = Math.ceil(word.length / 2), // determine the middle
i; // prepare the iteration variable
// loop from 0 to middle
for (i = 0; i <= middle; ++i) {
// check letter i against it counterpart on the opposite side
// of the word
if (word[i] !== word[(word.length - 1) - i]) {
// it is not a palindrom
return false;
}
}
// otherwise it is
return true;
}
// listen for clicks on the button and send the entered value to the palindrom function
document.querySelector('button').addEventListener('click', function(e) {
// obtain the input element
var element = document.querySelector('input');
// add/remove the 'palindrom' CSS class to the input field, depending on
// the output of palindrome function
if (palindrome(element.value)) {
element.classList.add('palindrome');
}
else {
element.classList.remove('palindrome');
}
});
input {
color: red;
}
input.palindrome {
color: green;
}
<input name=check placeholder=palindrome><button>check</button>
The text turns green if you have entered a palindrome successfully, red (default) otherwise.

JS function to validate input name not working correctly

The objective of this code is to check the name the user inputs. If the value contains something other than -abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ the function will throw an error.
I am unable to get this to work, and I'm not allowed to use Regular expressions. I've also tried String1.indexOf(usr.substr(i,1)) > -1) but that doesn't seem to work neither.
function nameValidation(username) {
var usr = document.getElementById("username").value;
usr = usr.trim();
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var ok = 1;
for (var i = 0; i < usr.length; i++) {
if (!isNaN(usr[i])) {
ok = 0;
break;
} else {
ok = 1;
document.getElementById("fnerror").innerHTML = "";
document.getElementById("username").style.borderColor = "lightgrey";
return true;
}
}
if (ok == 0) {
document.getElementById("fnerror").innerHTML = "X Enter Upper and lower case letters, hypen, apostrohe only please";
return false;
}
return true;
}
Something like this, maybe:
function isValidUsername(username) {
var alpha = "-'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
username = username.toUpperCase();
for (var i = 0, l = username.length; i < l; i++) {
if (alpha.indexOf(username[i]) === -1) return false;
}
return true;
}
Cheaper to upper-case the string and therefore have a shorter set of characters to test against (though probably marginal at best because there's a cost to even native-uppercasing..)
You can do it in a more "functional way", by using every method, which allow us to break a loop instead of foreach.
The every method executes the provided callback function once for each element present in the array until it finds one where callback returns a falsy value (a value that becomes false when converted to a Boolean). If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
Array.proototype.every
So :
function check(){
//Get value input and transform it into array
var value = document.querySelector('#username').value.split('');
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//If there is an error, stop the loop and return result
return value.every(function(elm){
//check if elm is an alpha string
return alpha.indexOf(elm) > -1;
});
}
The easiest (to understand at least) solution (that doesn't use regex), would be to loop through your string character by character and check .indexOf against your list of allowed characters, something like:
for (var i = 0; i < input.length; i++) {
if (alpha.indexOf(input[i])==-1) {
console.log("ERROR");
break;
}
}
EDITED: I read the question wrong and thought you wanted to return true if there's a letter. It will now make sure that each character is within the ASCII values of A and z.
text = "ABCDEFzzxasd1";
valid = true;
for( i = 0; i < text.length; i++ ) {
if ( text.charCodeAt(i) < 65 || text.charCodeAt(i) > 122 ) {
alert("Woah, that's not a letter!");
valid = false;
break;
}
}
Begin with
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('');
function duplicates( element, index, array ){
return array.indexOf(element) == index;
}
function isNameFormatCorrect( userName ){
return ( alpha.concat(username.split(''))
.filter( duplicates ).length === alpha.length );
}
Then
var username = "YourUserNameHere-"
isNameFormatCorrect( username ); => true;
var username = "YourUserNameHere-**"
isNameFormatCorrect( username ); => false;

Adding a hundredths place to a number that can be either comma or period delimited

I am wondering if this code can be modified so that it will render "4,5" and "4.5" (or any number that only has a tenths place) as 4.50 (or 4,50) respectively...rather than as 45.
I think I need to test "source" first to see if it's got the format "x[.,]x" (digit, comma or period, digit) but haven't been able to do that successfully. I've tried using "toFixed" but that messes things up if it's 4.500 or something (which needs to render as 4500, not 4.50!)
Any help would be hugely appreciated. Thank you!
function parse(source) {
var sep = source.charAt(source.length - 3);
switch (sep) {
case '.':
case ',':
var parts = source.split(sep);
var norm = parts[0].replace(/(\.|,|\s)/g, '') + '.' + parts[1];
break;
default:
var norm = source.replace(/(\.|,|\s)/g, '');
}
return Math.round(Number(norm));
}
So I have figured out a regex that identifies the right pattern: /^\d{1}[.,]\d{1}$/ (note there's a slash not showing up right before the period inside the brackets!!)
I have added it into the following little function, which I want to just tack on a zero or leave the variable as is. But for some reason it's now crashing at the part where I'm adding the zero...
function addZeros(number) {
var s = number;
if (s.match(/^\d{1}[\.,]\d{1}$/)) { //should only get here on "X,X" or "X.X" cases
alert(s); //makes it to here, displays only this alert
s = s.toFixed(2); //wtf is wrong with this?!!
alert(s); //does NOT make it to here.
return s;
}
else {
alert('All good in the hood.');
return s;
}
}
If I understand you correctly this should do it
function parse(s) {
var found = false;
['.', ','].forEach(function (el) {
var i = s.indexOf(el);
if (s[i] === s[s.length - 2]) {
s = s + '0';
found = true;
return false;
}
});
if (!found) {
return s.replace(/(\.|,|\s)/g, '');
} else {
return s;
}
}
Run a forEach on each delimiter and figure out how you want it to be formatted.
http://jsfiddle.net/Ek6cJ/
Does this do what you want?
function parse(source) {
var dotIndex = source.lastIndexOf('.');
var commaIndex = source.lastIndexOf(',');
var numDots = source.match(/\./g).length;
if (dotIndex > commaIndex && numDots == 1) {
// Dot-delimited decimal
return Number(source.replace(/,/g, '')).toFixed(2);
} else {
return Number(source.replace(/\./g, '').replace(/,/g, '.')).toFixed(2);
}
}
> parse("1,200,300.20")
"1200300.20"
> parse("1.200.300,20")
"1200300.20"
> parse("1.200.300")
"1200300.00"

Categories

Resources