PDA

View Full Version : How to evaluate multiple conditions in an if statement



chemixrx
Feb 7th, 2017, 04:29 AM
I am hoping someone can help me here, both with syntax and logic.

I have the following working calculation.



{
if (fieldname1 == 'A' || fieldname2 == 'A' || fieldname3 == 'A' || fieldname4 == 'A' || fieldname5 == 'A' || fieldname6 == 'A')
result = "Everything achieved"
else result = "A is missing";
}


I need the code to go one step further

if any of the fields (1 through 5) = A and B
result = "everything achived"

if any of the fields are missing A or B, the result needs to say

"A is missing"
or
"B is missing"
or
"A and B are missing"

Depending on which is missing. If A is missing, it needs to state it. Same with B. If both are missing, then it needs to say both. For some reason this is hurting my brain and I need you guys to help. I will seriously Paypal $10 to whoever solves this for me.

chemixrx
Feb 7th, 2017, 04:30 AM
Note: Result can also say "A is missing" "B is missing" it doesn't have to evaluate them together.

Philip M
Feb 7th, 2017, 08:25 AM
I am not sure that I understand your question - where does B fit in? Do the fields contain A or B, or A & B? Are you saying that all fields must be populated with either A or B? Assuming the fields are defined, you can test for an empty field with if (!fieldname1) {result = "fieldname1 is empty"}

You say if any of the fields (1 through 5) = A and B result = "everything achived"
but at the same time if any of the fields are missing A or B, the result needs to say "A is missing"
I don't understand this.

chemixrx
Feb 7th, 2017, 01:44 PM
I am not sure that I understand your question - where does B fit in? Do the fields contain A or B, or A & B? Are you saying that all fields must be populated with either A or B? Assuming the fields are defined, you can test for an empty field with if (!fieldname1) {result = "fieldname1 is empty"}

You say if any of the fields (1 through 5) = A and B result = "everything achived"
but at the same time if any of the fields are missing A or B, the result needs to say "A is missing"
I don't understand this.

Thanks for your time. I wanted to clarify but I didn't see where I could edit my post.

Yes, so there are 6 dropdown lists, and each has the following 2 options. A or B. Of those 6 fields, we must see one instance of A and one instance of B in order to get "everything achived"
else, if one of those 6 dropdowns doesn't have 'A' then "A is missing"
else, if one of those 6 dropdowns doesn't have 'A' then "A is missing"
if one of those 6 dropdowns doesn't have 'A' or 'B' then "A is missing" <page break> "B is missing"

Does that help?

chemixrx
Feb 7th, 2017, 01:45 PM
Second else should read if one of those 6 dropdowns doesn't have 'B' then "B is missing"

Ugh.. where's the edit button?

Goos
Feb 7th, 2017, 03:12 PM
function evaluate(){
var fields = [fieldname1, fieldname2, fieldname3, fieldname4, fieldname5, fieldname6];
var ret = 0; // 0b00
for(var i=0; i<fields.length; i++){
ret |= fields[i].selectedIndex; // turn on bit 1 0b01 or 2 0b10
}
return ['A and B are missing', 'B is missing', 'A is missing', 'Everything achieved'][ret]; // 0b00, 0b01, 0b10, 0b11
};

chemixrx
Feb 7th, 2017, 03:38 PM
function evaluate(){
var fields = [fieldname1, fieldname2, fieldname3, fieldname4, fieldname5, fieldname6];
var ret = 0; // 0b00
for(var i=0; i<fields.length; i++){
ret |= fields[i].selectedIndex; // turn on bit 1 0b01 or 2 0b10
}
return ['A and B are missing', 'B is missing', 'A is missing', 'Everything achieved'][ret]; // 0b00, 0b01, 0b10, 0b11
};

Thank you very much! Because I'm new and don't quite understand the logic here, could you add a third dropdown item "C" to this equation and follow the same logic through in code? This will allow me to evaluate and compare. Thanks again.

chemixrx
Feb 7th, 2017, 03:44 PM
I do understand that an array and for loops makes sense when evaluating several fields like this, and if statements are cumbersome. I don't understand the fancy use of hex in evaluating the content of each dropdown field.

Goos
Feb 7th, 2017, 04:51 PM
It get a little messier with more than two values.

function evaluate(){
var fields = [fieldname1, fieldname2, fieldname3, fieldname4, fieldname5, fieldname6],
msg = {
0: 'A, B and C are missing', // 000
1: 'B and C are missing', // 001
2: 'A and C are missing', // 010
4: 'A and B are missing', // 100
3: 'C is missing', // 011
5: 'B is missing', // 101
6: 'A is missing', // 110
7: 'Everything achieved' // 111
},
ret = 0,
i;
for(i=0; i<fields.length; i++){
ret |= 1 << sel[i].selectedIndex >> 1; // shift 0b1 bits equal to selectedIndex to the left, then shift one bit to the right to discard the empty option at selectedIndex[0]
}
return msg[ret];
};
Or with even more values

function evaluate(){
var fields = [fieldname1, fieldname2, fieldname3, fieldname4, fieldname5, fieldname6],
required = ['A','B','C','D','E','F'],
msg = [],
ret = 0,
i;
for(var i=0; i<fields.length; i++){
ret |= 1 << sel[i].selectedIndex >> 1;
}
for(var i=0; i<required.length; i++){
if(!(1<<i & ret)){
msg.push(required[i]);
}
}
if(msg.length == 0){
msg = 'Everything achieved';
} else if(msg.length == 1){
msg = msg[0] + ' is missing';
} else {
msg = msg.slice(0, -1).join(', ') +' and '+ msg.pop() +' are missing';
}
return msg;
};

chemixrx
Feb 7th, 2017, 04:54 PM
function evaluate(){
var fields = [fieldname1, fieldname2, fieldname3, fieldname4, fieldname5, fieldname6];
var ret = 0; // 0b00
for(var i=0; i<fields.length; i++){
ret |= fields[i].selectedIndex; // turn on bit 1 0b01 or 2 0b10
}
return ['A and B are missing', 'B is missing', 'A is missing', 'Everything achieved'][ret]; // 0b00, 0b01, 0b10, 0b11
};

OK so after reading it carefully, I am starting to understand the logic here.

You've assigned it like this

No dropdown selection = 0
A selected = 1
B selected = 2

Then the function evaluates each field and if it doesn't see a 0, 1 or 2, it returns the messages in order of evaluation. In reality, my formula may have 'A' 'B' 'C' 'D' or even 'E'. Can this code scale to include 4-5 variables? It would seem to me that it would need to capture every combination missing like this

return ['A and B and C are missing', 'B and C are missing', 'A and C are missing', 'A and B are missing', 'C is missing', 'A is missing', 'B is missing', 'Everything achieved'][ret]; // 0b00, 0b01, 0b10, 0b11
};[/code][/QUOTE]

Would this actually work?

chemixrx
Feb 7th, 2017, 04:55 PM
Holy crap.. You're good. That last one approaches what I need!

Goos
Feb 7th, 2017, 05:18 PM
Here is another approach of the last version. Removed the bitwise construction, because with more than two values it's just not as elegant as is should be.

function evaluate(){
var fields = document.getElementsByTagName('select'),
msg = ['A','B','C'],
i,
t;
for(i=0; i<fields.length; i++){
t = fields[i].value;
~msg.indexOf(t) && msg.splice(msg.indexOf(t), 1);
}
if(msg.length == 0){
msg = 'Everything achieved';
} else if(msg.length == 1){
msg = msg[0] + ' is missing';
} else {
msg = msg.slice(0, -1).join(', ') +' and '+ msg.pop() +' are missing';
}
return msg;
};

chemixrx
Feb 9th, 2017, 08:40 PM
Hey Goos,

You really, really helped me out here. You did a very good job deciphering my problem and gave me a wonderful solution which I was able to convert to my plugin by using the below


(function(){
var fields = document.getElementsByTagName('select'),
msg = ['A','B','C'],
i,
t;
for(i=0; i<fields.length; i++){
t = fields[i].value;
~msg.indexOf(t) && msg.splice(msg.indexOf(t), 1);
}
if(msg.length == 0){
msg = 'Everything achieved';
} else if(msg.length == 1){
msg = msg[0] + ' is missing';
} else {
msg = msg.slice(0, -1).join(', ') +' and '+ msg.pop() +' are missing';
}
return msg;
})()

Now I need to adjust the above calculation to do the following
Requirements
A
B
C
D
Any Two of the following: E,F,G,H,I

Example

User Input = A,B,C,D,E,H

"A requirement is fulfilled"

"B requirement is fulfilled"

"C requirement is fulfilled"

"D requirement is fulfilled"

"E and H fulfill the final requirements"

Alternative Example

User Input = A,B,D,G

"A requirement is fulfilled"

"B requirement is fulfilled"

"C requirement is not fulfilled"

"D requirement is fulfilled"

"G fulfills only one of the final two requirements. You need E, F, H, I"

-Alternative Example-

User Input = A,B

"A requirement is fulfilled"

"B requirement is fulfilled"

"C requirement is not fulfilled"

"D requirement is not fulfilled"

"You need two of the following: E,F,G,H,I "

I think you get the idea. I don't know this board's policy, but if you are able to write a script using the above logic then I will happily shoot you $20 over Paypal. This is for our startup business and this is a key piece of code. I want to compensate you for your time.

Goos
Feb 9th, 2017, 11:10 PM
This should work. No need for any payments, this was a good experience to brush up my skills working with bitwise operators.

function handler(){
var ret = evaluate(document.getElementsByTagName('select'));
console.log(createMsg(ret));
return createMsg(ret);
};

function evaluate(fields){
var ret = 0, i;
for(var i=0; i<fields.length; i++){
ret |= 1 << fields[i].selectedIndex >> 1;
}
return ret;
};

function createMsg(inp){
var reqs = ['A','B','C','D','E','F','G','H','I'],
msg = [],
f = [], // fulfilled
u = [], // unfulfilled
cmbs = [16|32, 16|64, 16|128, 16|256, 32|64, 32|128, 32|256, 64|128, 64|256, 128|256].reduce(function(o, v){
o[v] = true;
return o;
}, {});

for(i=0; i<4; i++){
msg.push(reqs[i] + ' requirement is '+ (inp & 1<<i ? '' : 'not ') +'fulfilled.');
}

for(; i<reqs.length; i++){
(1<<i & inp) ? f.push(reqs[i]) : u.push(reqs[i]);
}
// inp & ~15 turns off the first 4 bits
if((inp & ~15) == 0){
msg.push('You need two of the following: '+ u.join(' ') +'.');
}
else if((inp & ~15) in cmbs){
msg.push(f.join(' and ') + ' fulfill the final requirements.');
}
else {
msg.push(f[0] + ' fulfills only one of the final two requirements. You need one of '+ u.join(' ') +'.');
}
return msg;
};

chemixrx
Feb 12th, 2017, 04:36 AM
Hey Goos, thanks very much! Sorry to ask a stupid question, but which of my examples does the above code satisfy?

Don't you have to input the reqs that are 'any one of' and 'any two of' separately somewhere? I just don't see a place for those.

Goos
Feb 12th, 2017, 11:02 AM
I should satisfy all of them. All the required combinations are in the cmbs object.
16|32 = 48 = 0b000110000 = EF
16|64 = 72 = 0b001010000 = EG

But now I thought about it a bit more, I realized there is no need to declare them. You could just check the lengths of the fullfilled and unfulfilled array, it will tell you if all requirements are met.


function createMsg(inp){
var reqs = ['A','B','C','D','E','F','G','H','I'],
msg = [],
f = [], // fulfilled
u = [], // unfulfilled

for(i=0; i<4; i++){ // loop over the single requirements A,B,C,D
msg.push(reqs[i] + ' requirement is '+ (inp & 1<<i ? '' : 'not ') +'fulfilled.');
}

for(; i<reqs.length; i++){ // loop over the combined requirements E,F,G,H,I. When a req is met, push it to the 'f' array else to the 'u' array
(1<<i & inp) ? f.push(reqs[i]) : u.push(reqs[i]);
}

if(f.length == 0){
msg.push('You need two of the following: '+ u.join(' ') +'.');
}
else if(f.length >= 2){
msg.push(f.join(' and ') + ' fulfill the final requirements.');
}
else {
msg.push(f[0] + ' fulfills only one of the final two requirements. You need one of '+ u.join(' ') +'.');
}
return msg;
};