Loop thru array to make sure criteria is met on every item - javascript

I have an array of items. I want to make sure every item meets a certain criteria.
I wrote this for loop but I'm not sure if it's the most efficient. Is there a better way to do this?
let match = 0;
for (var i = 0; i < lastPressed.length; i++) {
if (lastPressed[i].o.length === 1 && lastPressed[i].n.length === 0) {
match++;
} else {
break;
}
}
if(match === lastPressed.length) return true;
return false;

Javascript has a function just for this: Array.prototype.every.
return lastPressed.every(v => v.o.length === 1 && v.n.length === 0);

Using builtin every is the best choice here.
However, assuming you want to do it by yourself (for fun, for learning), notice that you don't have to check every item in the array. It's because the very first item that doesn't match the criteria should fail the whole process.
You just have to reverse the condition then. You don't need the count.
for (var i = 0; i < lastPressed.length; i++) {
if (!(lastPressed[i].o.length === 1 && lastPressed[i].n.length === 0)) {
return false;
}
}
return true;
It's exactly your code but the loop terminates when you find the first nonmatching element.

You could take a for ... of statement and exit early.
This approach uses a destructuring assignment and a negated condition for the check.
for (const { o, n } of lastPressed) {
if (o.length !== 1 || n.length !== 0) return false;
}
return true;

Related

Return "True" if all the characters in a string are "x" or "X" else return false

I am looking at this code challenge:
Complete the function isAllX to determine if the entire string is made of lower-case x or upper-case X. Return true if they are, false if not.
Examples:
isAllX("Xx"); // true
isAllX("xAbX"); // false
Below is my answer, but it is wrong. I want "false" for the complete string if any of the character is not "x" or "X":
function isAllX(string) {
for (let i = 0; i < string.length; i++) {
if (string[i] === "x" || string[i] === "X") {
console.log(true);
} else if (string[i] !== "x" || string[i] !== "X") {
console.log(false);
}
}
}
isAllX("xAbX");
Your loop is outputting a result in every iteration. There are two issues with that:
You should only give one result for an input, so not in every iteration; currently you are reporting on every single character in the input string.
You are asked to return a boolean result (false/true), not to have the function print something. That should be left to the caller
You could take a simpler approach though, and first turn the input string to all lower case. Now you only have to look for "x". Then take out all "x" and see if something is left over. You can check the length property of the resulting string to decide whether the return value should be false or true:
function isAllX(string) {
return string.toLowerCase().replaceAll("x", "").length == 0;
}
console.log(isAllX("xxXXxxAxx")); // false
console.log(isAllX("xxXXxxXxx")); // true
If you are confortable with regular expressions, you could also use the test method:
function isAllX(string) {
return /^x*$/i.test(string);
}
console.log(isAllX("xxXXxxAxx")); // false
console.log(isAllX("xxXXxxXxx")); // true
You can try this way.
function isAllX(str) {
let isX = true;
let newString = str.toLowerCase();
for (let i = 0; i < newString.length; i++) {
if (newString[i] !== "x") {
isX = false;
}
}
return isX;
}
console.log(isAllX("xAbX"));
console.log(isAllX("XXXxxxXXXxxx"));
You can use regex to find the same.
function allX(testString) {
return /^x+$/i.test(testString);
}
console.log(allX("xxXX"));
console.log(allX("xxAAAXX"));
Without any method if you want
function isAllX(str) {
let flag = true;
for (let i = 0; i < str.length; i++) {
if (str[i] !== "x" && str[i] !== "X") {
flag = false;
// break;
}
}
return flag;
}
console.log(isAllX("xAbX"));
console.log(isAllX("XXXxxxXXXxxx"));
console.log(isAllX("xx"));
You can try converting the string to a single case, then looping over it while checking for the condition as below
function isAllX(string) {
const newString = string.toUpperCase();
for (let i = 0; i < newString.length; i++) {
if (newString[i] !== "X") {
return false
}
}return true
}

check the alphabetical order

I am a newbie who is trying hard to have a grip on javascript. please help me to consolidate my fundamentals.
input will be a string of letters.
following are the requirements.
function should return true if following conditions satisfy:
letters are in alphabetical order. (case insensitive)
only one letter is passed as input. example :
isAlphabet ('abc') === true
isAlphabet ('aBc') === true
isAlphabet ('a') === true
isAlphabet ('mnoprqst') === false
isAlphabet ('') === false
isAlphabet ('tt') === false
function isAlphabet(letters) {
const string = letters.toLowerCase();
for (let i = 0; i < string.length; i++) {
const diff = string.charCodeAt(i + 1) - string.charCodeAt(i);
if (diff === 1) {
continue;
} else if (string === '') {
return false;
} else if (string.length === 1) {
return true;
} else {
return false;
}
}
return true;
}
It's generally a better practice to start your function off with dealing with the edge-cases rather than putting them somewhere in the middle. That way, the function returns as soon as it can - and it's a lot easier to read than a waterfall of if..else statements.
function isAlphabet(letters) {
if ("" == letters) {
return false;
}
if (1 == letters.length) {
return true;
}
const string = letters.toLowerCase();
// carry on with your loop here.
}
You've got the right idea, but it can be simplified to just fail on a particular error condition, i.e when a smaller character follows a larger one:
function isAlphabet(letters) {
const string = letters.toLowerCase();
let lastChar;
for (let i = 0; i < string.length; i++) {
// Grab a character
let thisChar = string.charCodeAt(i);
// Check for the failure case, when a lower character follows a higher one
if (i && (thisChar < lastChar)) {
return false;
}
// Store this character to check the next one
lastChar = thisChar;
}
// If it got this far then input is valid
return true;
}
console.log(isAlphabet("abc"));
console.log(isAlphabet("aBc"));
console.log(isAlphabet("acb"));
You can use the simple way to achieve the same as below
function isAlphabet(inputString)
{
var sortedString = inputString.toLowerCase().split("").sort().join("");
return sortedString == inputString.toLowerCase();
}
console.log("abc = " + isAlphabet("abc"));
console.log("aBc = " + isAlphabet("aBc"));
console.log("acb = " + isAlphabet("acb"));
console.log("mnoprqst = " + isAlphabet("mnoprqst"));
Note: Mark the answer is resolves your problem.

Loop to determine whether digits of a number meet a condition (Javascript)

So, I am trying to create a function that determines whether a number is 'tidy'. (i.e. Each digit in the given integer is greater than the one that came before it.)
I have successfully managed to convert the integer into an array. But when I loop through it, I don't get the desired true for tidy and false, if otherwise. I am wondering what I am doing wrong?
function tidyNumber(n){
var arr = n.toString(10).split("").map(function(t){return parseInt(t)});
let tof;
if(arr.length == 1){
return true;
}
for(i = 0; i < arr.length; i++){
if(arr[i] <= arr[i+1]){
tof = true;
} else if(arr[i] > arr[i+1]){
tof = false;
}
}
return tof;
}
You could check only if a previous digit is greater than the actual digit and exit the function with false.
Then you need to start at index 1 and prevent checking a not given index.
function tidyNumber(n) {
var arr = Array.from(n.toString(), Number),
i; // declare, otherwise its a global variable
for (i = 1; i < arr.length; i++) {
if (arr[i - 1] > arr[i]) return false;
}
return true;
}
console.log(tidyNumber(1234)); // true
console.log(tidyNumber(1)); // true
console.log(tidyNumber(1223334)); // true
console.log(tidyNumber(51223334)); // false
To answer your question: The reason your function does not return the desired result is that is only returns the last value of tof. So your function currently only reports whether the last two digits of a number are tidy. To use the example of #Seblor, 1324:
First, the code will check whether 1 < 3 and set tof = true.
Next, it will check whether 3 < 2 and set tof = false.
Next, it will check whether 2 < 4 and set tof = true. This erases the actual result that you were seeking.
Incidentally, the code will finally check whether 4 < undefined (as #Pointy mentioned) but will not change the value of tof since neither conditional expression was satisfied.
You can achieve the desired behavior by returning the false result immediately when tof = false (as #nina-scholz suggested). Here is what that might look like within your code:
function tidyNumber(n){
var arr = n.toString(10).split("").map(function(t){return parseInt(t)});
let tof;
if(arr.length == 1){
return true;
}
for(i = 0; i < arr.length; i++){
if(arr[i] <= arr[i+1]){
tof = true;
} else if(arr[i] > arr[i+1]){
tof = false;
return tof; // <-- Added return statement here
}
}
return tof;
}
I hope that helps!
Try like this:
function tidyNumber(n){
current = 0;
while(n){
if(current > n % 10){
return false;
}
current = n % 10;
n = parseInt(n / 10);
}
return true;
}
The idea is to by "% 10" to get the remainder of a division by 10. This will get you the last digit. Look if its smaller then the one before, else loop until the number is zero!

checking strings in an array

I'm trying to see if the string in the first element of the array contains all of the letters of the string in the second element of the array.
For example
['hello', 'hey'] = false;
['Army', 'Mary'] = true;
Here is my code
function mutation(arr) {
a = arr[0].toLowerCase().split("");
b = arr[1].toLowerCase().split("");
for(i = 0; i < a.length; i++){
if(b.indexOf(a[i]) != -1){
console.log('true');
} else {
console.log('false');
}
}
}
mutation(['Army', 'Mary']);
UPDATED
I need to see if element 1 contains all the letters for element 2 before I return back anything.
This would do, I'm sure there are better and optimal solutions though,
1) Storing the return result in a boolean, as var result = true;.
2) Check if both the Strings are equal/same, no need to loop, return the result which is true.
3) loop through each characters and see if the target element contains them, if found a mismatch set, result to false, break and return result.
function mutation(arr) {
a = arr[0].toLowerCase().split("");
b = arr[1].toLowerCase().split("");
var result = true;
if(a === b)
return result;
for(i = 0; i < a.length; i++){
if(b.indexOf(a[i]) === -1){
result = false;
break;
}
}
return result;
}
mutation(['Army', 'Mary']);
UPDATE Added a condition if (a === b) return true; to skip for loop.
No need of loop, you can take advantage of array functions.
Steps
Sort both arrays
Cast to the string
Check if strings2 contains string1
function mutation(arr) {
var a = arr[0].toLowerCase().split(''),
b = arr[1].toLowerCase().split('');
// For exact equality
return a.sort().toString() === b.sort().toString();
// return b.sort().toString().indexOf(a.sort().toString()) > -1;
}
document.write('Army and Mary: ' + mutation(['Army', 'Mary'])); // true
document.write('<br />a and b: ' + mutation(['a', 'b'])); // false
document.write('<br />ab and abc: ' + mutation(['ab', 'abc'])); // false
Simply you need to loop throught the second element letters and return false if a character doesn't exist in first element, or continue the loop if it exists.
Then check if the counter is equal to your string length then it contains all the given letters and return true:
function mutation(arr) {
a = arr[1].toLowerCase().split("");
b = arr[0].toLowerCase().split("");
if (a === b) return true;
for (i = 0; i < a.length; i++) {
if (b.indexOf(a[i]) === -1) {
return false;
}
}
if (i === a.length) {
return true; // all the letteers of element one exists in the second element
}
}
if (mutation(['Army', 'Mary'])) {
alert("Element one contains all letters of second element !");
} else {
alert("Sorry!");
}
Note:
Make sure you loop throught the second element characters and not the first one, see the a = arr[1].toLowerCase().split("");.
//mutation function work ignoring case and order of character in strings
function mutation(arr) {
var first = arr[0].toLowerCase();
var second = arr[1].toLowerCase();
for(var i = 0; i < second.length; i++){
if(first.indexOf(second[i]) == -1){
return false;
}
}
return true;
}
//this returns true
mutation(["hello", "ol"]);

Dynamic condition in IF statement

I want to make condition of if statement dynamically in javascript,
check my code
var t = ['b','a']
if(t[0] !== 'a' && t[1] !== 'a'){console.log('remaining element')}
here t might be vary at any time say t = ['b','a','c'] then I need to write if condition like this
if(t[0] !== 'a' && t[1] !== 'a' && t[2] !== 'a'){console.log('remaining element')}
How can I rewirte this code efficiently?
You can use Array.prototype.every like this
if (t.every(function(currentElement) { return currentElement !== "a"; })) {
console.log('remaining element');
}
This works with arbitrary number of elements.
On older environments which do not support Array.prototype.every, you can use the plain for loop version
var flag = true;
for (var i = 0 ; i < t.length; i += 1) {
if (t[i] === "a") {
flag = false;
break;
}
}
if (flag) {
console.log('remaining element');
}

Categories

Resources