trying to loop through an array where the elements are object - javascript

I'm wondering why the code outputs false when you can see in the object that Wednesday = 34. I think i might have problems with changing the i variable.
var lookup = [{"Monday" : 12}, {"Wednesday" : 34},{"Thursday" : 0},{"Saturday" : 56} ]
// console.log(lookup[1]["Wednesday"] == 34) // prints out true
function ami(day, num){
var a;
for(var i = 0; i < lookup.length; i++){
if(lookup[i][day] == num ||
day == "Tuesday" && num >95 ||
day == "Friday" && num %2 == 0 ||
day == "Sunday" && num == 666 ||
day == "Sunday" && num == -666){
a = true
}else{
a = false
}
}
return a;
}
console.log(ami("Wednesday", 34))

You are rewriting the value of a with each iteration of the for loop. In essence, what you are doing is checking the last item of the lookup array, since the previous results are always overwritten.
I don't know exactly what you're trying to achieve with the conditions, but this could be what you need:
function ami(day, num){
for(var i = 0; i < lookup.length; i++){
if(lookup[i][day] == num ||
day == "Tuesday" && num >95 ||
day == "Friday" && num %2 == 0 ||
day == "Sunday" && num == 666 ||
day == "Sunday" && num == -666){
return true;
}
}
return false;
}

When your code reaches i=1, a gets indeed set to true. But after that the loop is allowed to continue, so when i gets incremented to 2, a gets set to false again.
You can fix this by returning from the function as soon as you determine the return value should be true:
var lookup = [{"Monday" : 12}, {"Wednesday" : 34},{"Thursday" : 0},{"Saturday" : 56} ]
function ami(day, num){
for(var i = 0; i < lookup.length; i++){
if(lookup[i][day] == num ||
day == "Tuesday" && num >95 ||
day == "Friday" && num %2 == 0 ||
day == "Sunday" && num == 666 ||
day == "Sunday" && num == -666){
return true;
}
}
}
console.log(ami("Wednesday", 34));
You can simplify the code even further if you use an ordinary object as your lookup table:
var lookup = {"Monday" : 12, "Wednesday" : 34, "Thursday" : 0, "Saturday" : 56};
function ami(day, num){
return (lookup[day] == num ||
day == "Tuesday" && num >95 ||
day == "Friday" && num %2 == 0 ||
day == "Sunday" && num == 666 ||
day == "Sunday" && num == -666);
}
console.log(ami("Wednesday", 34));

A Array.some() should do it.
var lookup = [{ "Monday": 12 }, { "Wednesday": 34 }, { "Thursday": 0 }, { "Saturday": 56 }];
function ami(day, num) {
return lookup.some(function (a) { return a[day] === num; }) ||
day == "Tuesday" && num > 95 ||
day == "Friday" && num % 2 == 0 ||
day == "Sunday" && num == 666 ||
day == "Sunday" && num == -666
}
document.write(ami("Wednesday", 34));
The other possibillity is to optimise the lookup array to an object with more than one property, like
var lookup = { "Monday": 12, "Wednesday": 34, "Thursday": 0, "Saturday": 56 };
The other version is this. I took your code and changed the behaviour of the condition and the loop condition as well. So the given conditions are first evaluated and then if necessary the iteration over the array. The variable a is taken as well as indicator to stop the iteration as well as the return value.
var lookup = [{ "Monday": 12 }, { "Wednesday": 34 }, { "Thursday": 0 }, { "Saturday": 56 }];
function ami(day, num) {
var a = false;
if (day == "Tuesday" && num > 95 ||
day == "Friday" && num % 2 == 0 ||
day == "Sunday" && num == 666 ||
day == "Sunday" && num == -666) {
a = true;
}
for (var i = 0; !a && i < lookup.length; i++) {
a = lookup[i][day] == num;
}
return a;
}
document.write(ami("Wednesday", 34));

Related

Javascript refactroing series of if else statement

I have a method and attached an event listener like below.
This method looks ugly. Is there any other way to refactor?
Any suggestions or ideas would be appreciated.
document.querySelector('dateInput').addEventListener('input', func.validateCalendar, false);
const func = {
validateCalendar({target}){
const tmpArr = Array.from(target.value.replace(/[^0-9\.]/g, ''));
if( tmpArr.length === 0 ){
target.value = '';
}else if( tmpArr.length === 4){
target.value = tmpArr.join('');
}else if( tmpArr.length === 5 ){ //month first digit
const month1 = +tmpArr[4]
console.log('len:5, month1: ', month1);
if( month1 > 1 ){
tmpArr.splice(4,1, '');
}
tmpArr.splice(4,0, '-');
target.value = tmpArr.join('');
}else if( tmpArr.length === 6){ //month second digit
const month1 = +tmpArr[4];
const month2 = +tmpArr[5];
const cond1 = month1 === 0 && month2 === 0;
const cond2 = month1 === 0 && month2 > 9;
const cond3 = month1 === 1 && month2 > 2
if( cond1 || cond2 || cond3 ){
tmpArr.splice(5,1, '');
}
tmpArr.splice(4,0, '-');
target.value = tmpArr.join('');
}else if( tmpArr.length === 7 ){ //day first digit
const month = +tmpArr.slice(4,6).join('');
const day1 = +tmpArr[6];
console.log('len 7 : day1 ', day1);
const cond1 = month !== 2 && day1 > 3;
const cond2 = month === 2 && day1 > 2
if( cond1 || cond2 ){
tmpArr.splice(6,1, '');
}
tmpArr.splice(4,0, '-')
tmpArr.splice(7,0, '-');
target.value = tmpArr.join('');
}else if( tmpArr.length === 8 ){ //day second digit
const year = +tmpArr.slice(1,4).join('');
const month = +tmpArr.slice(4,6).join('');
const day = +tmpArr.slice(6,8).join('');
const monthsIn31 = [1, 3, 5, 7, 8, 10, 12];
const monthsIn30 = [4, 6, 9, 11];
const cond1 = day === 0;
const cond2 = monthsIn31.includes(month) && day > 31;
const cond3 = monthsIn30.includes(month) && day > 30;
const cond4 = month === 2;
if( cond1 || cond2 || cond3){
tmpArr.splice(7,1, '');
}
if( cond4 ){
const cond1 = moment([year]).isLeapYear() && day > 29;
const cond2 = !moment([year]).isLeapYear() && day > 28
if( cond1 || cond2 ){
tmpArr.splice(7,1, '');
}
}
console.log('len 8 : ', target.value);
tmpArr.splice(4,0, '-')
tmpArr.splice(7,0, '-');
target.value = tmpArr.join('');
}else if( tmpArr.length > 8 ){
target.value = target.value.slice(0, -1);
}
},
}
You can try switch..case if you just check a variable again and again.
Thus if you currently have:
var a = 5
if(a === 5){
console.log("Five");
} else if(a === 7) {
console.log("Seven");
} else if (a === 9) {
console.log("Nine");
}
// ... and so on
else {
console.log("Irrelevant");
}
This is equivalent switch..case for it
var a = 5
switch(a) {
case 5:
console.log("Five");
break;
case 7:
console.log("Seven");
break;
// ... and so on
default:
console.log("Irrelevant");
}
However, meanwhile the if..else if uses curly brackets {} to limit the scope of the condition, switch..case uses break to limit it. The default in the switch..case is equivalent to the else in if..else, if and only if you put the break properly.
If you forget to put break, it will execute every cases placed under the satisfied condition until it finds the break or return or the default or the closing curly bracket } of the switch..case statement.

Can a Javascript condition be between numbers?

I'm looking to identify a category based on this table:
I have an if statement that seems to work for some conditions, but not others. R, P, and Q are working, but conditions that go between numbers aren't returning the right category.
If statement:
function getCategory(featureFunctionalScore, featureDysfunctionalScore) {
if (featureFunctionalScore == 4 && featureDysfunctionalScore == -2) {
return "Performance";
} else if (featureFunctionalScore == 4 && featureDysfunctionalScore <= -1 && featureDysfunctionalScore > 4) {
return "Attractive"
} else if (featureFunctionalScore <= -1 && featureFunctionalScore > 4 && featureDysfunctionalScore == 4) {
return "Expected"
} else if ((featureFunctionalScore >= -2 && featureFunctionalScore <= 2 && featureDysfunctionalScore == -2) || (featureFunctionalScore == -2 && featureDysfunctionalScore >= -2 && featureDysfunctionalScore <= 2)) {
return "Reverse"
} else if ((featureFunctionalScore == 4 && featureDysfunctionalScore == -2) || (featureFunctionalScore == 2 && featureDysfunctionalScore == -1) || (featureFunctionalScore == -1 && featureDysfunctionalScore == 2) || (featureFunctionalScore == -2 && featureDysfunctionalScore == 4)) {
return "Questionable"
} else {
return "Indifferent"
};
};
Am I missing something important?
Update
This statement works in Excel, but I'm struggling to get it to work in JS:
=IF(OR(AND(C3 <= 2, B3 <= -1), AND(C3 <= -1, B3 <= 2)), "R", IF(AND(C3 <= 2, C3 >= -1, B3 <= 2, B3 >= -1), "I", IF(AND(C3 >= 2,B3 >= -1, B3 <= 2),"A", IF(AND(C3 <= 2, B3 <= 4, B3 >= 2), "M", IF(AND(C3 >= 2, B3 >= 2), "P", "Q")))))
This should be what you're looking for. I'm sure it could be optimized, but it works. JSFiddle: https://jsfiddle.net/yxb7tr9n/
function getCategory(x,y){
var answer = -999;
if (x == 4 && y == 4){
answer = "p";
}else if([-1,0,2].indexOf(x) >= 0 && y == 4){
answer = "A";
}else if((x == -2 && y == 4) || (x == -1 && y == 2) || (x == 4, y == -2)){
answer = "Q";
}else if(x == 4 && [-1,0,2].indexOf(y) >= 0) {
answer = "M";
}else if((x == -1 && [-1,0].indexOf(y) >= 0) || (x == 0 && [-1,0,2].indexOf(y) >= 0) || (x == 2 && [0,2].indexOf(y) >= 0)){
answer = "I";
}else if ((x == -2 && [-2,-1,0,2].indexOf(y) >= 0) || (y == -2 && [-2,-1,0,2].indexOf(x) >= 0)) {
answer = "R";
}else{
answer = "??";
}
return answer;
}
UPDATE: Alternate version using a coordinate mapping system. JSFiddle: https://jsfiddle.net/g2d6p4rL/4/
function indexOfCustom (parentArray, searchElement) {
for ( var i = 0; i < parentArray.length; i++ ) {
if ( parentArray[i][0] == searchElement[0] && parentArray[i][1] == searchElement[1] ) {
return i;
}
}
return -1;
}
function getCategory2(x,y){
var p = [[4,4]];
var q = [[-2,4],[-1,2],[2,-1],[4,-2]];
var a = [[-1,4],[0,4],[2,4]];
var m = [[4,2],[4,0],[4,-1]];
var i = [[0,2],[2,2],[-1,0],[0,0],[2,0],[-1,-1],[0,-1]];
var r = [[-2,2],[-2,0],[-2,-1],[-2,-2],[-1,-2],[0,-2],[2,-2]];
coord = [x,y];
if (indexOfCustom(p,coord) >= 0){
return "p";
} else if (indexOfCustom(q,coord) >= 0){
return "Q";
} else if (indexOfCustom(a,coord) >= 0){
return "A";
} else if (indexOfCustom(m,coord) >= 0){
return "M";
} else if (indexOfCustom(i,coord) >= 0){
return "I";
} else if (indexOfCustom(r,coord) >= 0){
return "R";
}else{
return "??";
}
}
Output of all answers:
[-2,-2] = R
[-2,-1] = R
[-2,0] = R
[-2,2] = R
[-2,4] = Q
[-1,-2] = R
[-1,-1] = I
[-1,0] = I
[-1,2] = Q
[-1,4] = A
[0,-2] = R
[0,-1] = I
[0,0] = I
[0,2] = I
[0,4] = A
[2,-2] = R
[2,-1] = Q
[2,0] = I
[2,2] = I
[2,4] = A
[4,-2] = Q
[4,-1] = M
[4,0] = M
[4,2] = M
[4,4] = p

Why is my If-Else statement defaulting to "else"?

I'm new to JavaScript and have just been toying with this little IF-ELSE exercise. Essentially, slots 1 thru 4 are static to experiment with the || operator. The const 'testSlot' is one that I've altered as time passes to try and execute the "else if" segment of my code; e.g, if it's 9:10 PM I've
just been manually changing the getHours to 21 and the getMinutes to 10 and then run the code.
With that said, I can't get either of the first two console.logs to run, it always just runs the "else", which is three.
My question is mostly if my usage the of the date object was wrong or if the syntax in my If-Else statement was wrong. A pointer in the right direction would be very much appreciated.
Here is my code:
const now = new Date();
const slot1 = now.getHours === 12 && getHours.getMinutes === 1;
const slot2 = now.getHours === 12 && getHours.getMinutes === 2;
const slot3 = now.getHours === 12 && getHours.getMinutes === 3;
const slot4 = now.getHours === 12 && getHours.getMinutes === 4;
const testSlot = now.getHours === 20 && getHours.getMinutes === 34;
if (slot1 || slot2 || slot3 || slot4) {
console.log('one');
} else if (testSlot) {
console.log('two');
} else {
console.log('three');
};
.getHours() and .getMinutes() are both functions and require parenthesis after. Also, getHours.getMinuets() wouldn't do anything. You have to do now.getMinutes(). I updated your snippet for you. It will still console.log three but that's only because all the if statements are false. Wait till its 12:01 and it should say one.
const now = new Date();
const slot1 = now.getHours() === 12 && now.getMinutes() === 1;
const slot2 = now.getHours() === 12 && now.getMinutes() === 2;
const slot3 = now.getHours() === 12 && now.getMinutes() === 3;
const slot4 = now.getHours() === 12 && now.getMinutes() === 4;
console.log(now.getHours());
console.log(now.getMinutes());
const testSlot = now.getHours() === 20 && now.getMinutes() === 34;
if (slot1 || slot2 || slot3 || slot4) {
console.log('one');
} else if (testSlot) {
console.log('two');
} else {
console.log('three');
};

Simple modulo tester

I have a simple, modulo based script, which runs for 3 and 6 digits to else. There are also cases for these numbers, which condition should fit also to these numbers.
function caffeineBuzz(n){
var returnvalue;
if (n % 3 == 0)
returnvalue = "Java";
if (n % 3 == 0 && n % 4 == 0)
returnvalue = "Coffee";
if (n % 3 == 0 && n % 2 == 0)
returnvalue = "Java" + "Script"
if (n % 4 == 0 && n % 2 == 0)
returnvalue = "Coffee" + "Script"
else
returnvalue = "mocha_missing!"
return returnvalue;
}
n stands for input, that is an integer and returnvalue should be a string.
Update:
Most specific -> less specific approach helped me, but there are cases, when it returns with wrong value.
function caffeineBuzz(n){
var returnvalue;
if (n % 4 == 0)
returnvalue = "Coffee" + "Script"
else if (n % 3 == 0 && n % 4 == 0)
returnvalue = "Coffee";
else if (n % 3 == 0 && n % 2 == 0)
returnvalue = "Java" + "Script"
else if (n % 3 == 0)
returnvalue = "Java";
else
returnvalue = "mocha_missing!"
return returnvalue;
}
This function is the guesstimation of the answer based on comments.
function caffeineBuzz(n){
//Storing n's modulos to not calculate them multiple times
var mod3 = (n % 3 == 0)
var mod4 = (n % 4 == 0);
var mod2 = mod4 || (n % 2 == 0);
//Maybe: return (mod3 ? ("Java" + (mod4 ? "Coffee" : "")) + (mod2 ? "Script" : "") : "mocha_missing!");
return (mod3 ? ((mod4 ? "Coffee" : "Java") + (mod2 ? "Script" : "")) : ("mocha_missing!"));
}

Is there any way to optimise this JavaScript further (comparing current time to opening hours)?

I am setting up some JavaScript to compare the current time to a venue's opening and closing hours (potentially different each day, so different var for each day).
Here's what I have so far:
// Compare current time to today's hours
if (day === 1 && time > monOpen && time < monClose) {
venueIsOpen();
} else if (day === 2 && time > tuesOpen && time < tuesClose) {
venueIsOpen();
} else if (day === 3 && time > wedOpen && time < wedClose) {
venueIsOpen();
} else if (day === 4 && time > thursOpen && time < thursClose) {
venueIsOpen();
} else if (day === 5 && time > friOpen && time < friClose) {
venueIsOpen();
} else if (day === 6 && time > satOpen && time < satClose) {
venueIsOpen();
} else if (day === 0 && time > sunOpen && time < sunClose) {
venueIsOpen();
} else {
venueIsClosed();
}
Obviously very straightforward - is there any way to optimise this?
First of all, we can combine a load of those if statements:
// Compare current time to today's hours
if (day === 1 && time > monOpen && time < monClose ||
day === 2 && time > tuesOpen && time < tuesClose ||
day === 3 && time > wedOpen && time < wedClose ||
day === 4 && time > thursOpen && time < thursClose ||
day === 5 && time > friOpen && time < friClose ||
day === 6 && time > satOpen && time < satClose ||
day === 0 && time > sunOpen && time < sunClose) {
venueIsOpen();
} else {
venueIsClosed();
}
That's still quite ugly, right? But there's some logic in there... We could use arrays for the open / close times:
var open = [sunOpen, monOpen, tuesOpen, wedOpen, thursOpen, friOpen, satOpen],
close = [sunClose, monClose, tuesClose, wedClose, thursClose, friClose, satClose];
if(time > open[day] && time < close[day])
venueIsOpen();
else
venueIsClosed();
Or, even shorter using a ternary condition:
(time > open[day] && time < close[day] ? venueIsOpen : venueIsClosed)();
Here's another way that could shorten your code:
// These are the 7 days of the week
var openings = [
{opening: 1,close: 2},
{opening: 2,close: 4},
{opening: 5,close: 7},
{opening: 1,close: 5},
{opening: 1,close: 3},
{opening: 2,close: 9},
{opening: 1,close: 2}
];
// loop through all of them
for(var i=0, l=openings.length; i<l; i++) {
// if the current time is bigger than the current day opening time and smaller than the current closing time call venueIsOpen(), otherwise call venueIsClosed()
(openings[day].opening < time && openings[day].close > time) ? venueIsOpen() : venueIsClosed();
}

Categories

Resources