3

i have write a function to place "," and "and" in between three links how could i reduce if else statements. In javascript, i get count if count is not zero means link have to show otherwise it shoud be hide

in following scenario

function inst_grammer()
{
var otherCount = parseInt($('.global_other_count').html());
var initCount = parseInt($('.global_init_count').html());
var signCount = parseInt($('.global_sign_count').html());

var init_class = $('.inst_init');
var sign_class =  $('.inst_sign');

if (signCount != 0 && initCount != 0 && otherCount == 0)
{
    init_class.html('').fadeOut();
    sign_class.html(' and ').fadeIn();
} else if (signCount == 0 && initCount != 0 && otherCount != 0)
{
    init_class.html(' and ').fadeIn();
    sign_class.html('');
} else if (signCount != 0 && initCount != 0 && otherCount != 0)
{
    init_class.html(' and ').fadeIn();
    sign_class.html(' , ').fadeIn();
}
else if (signCount != 0 && initCount == 0 && otherCount == 0)
{
    init_class.html('').fadeOut();
    sign_class.html('').fadeOut();
}
else if (signCount == 0 && initCount != 0 && otherCount == 0)
{
    init_class.html('').fadeOut();
    sign_class.html('').fadeOut();
}
else if (signCount == 0 && initCount == 0 && otherCount != 0)
{
    init_class.html('').fadeOut();
    sign_class.html('').fadeOut();
}
else if (signCount != 0 && initCount == 0 && otherCount != 0)
{
    init_class.html('').fadeOut();
    sign_class.html(' and ').fadeIn();
}
}
Zaheer
  • 402
  • 6
  • 20

5 Answers5

9

I think everyone is looking at this problem in the wrong way. It is not about simplifying the if's, but about the algorithm for inserting "," and "and" separators in grammatical sequence.

Any solution to this problem should allow for any number of items (not just the 3 specified). Otherwise you potentially get a greatly increasing number of if tests if the spec changes. Certainly more reusable (i.e. if the business needs change).

I gather the intention, in this example, is to provide a display that shows these options:

  • "a, b and c"
  • "a and b"
  • "a and c"
  • "b and c"
  • "a"
  • "b"
  • "c"

So the rules are:

  • if the number of display items is 1, display no separators
  • if the number of display items is 2, display "and" between the items
  • if the number of items is 3, use "," instead of "and" except for the last one.

So basically for n > 1, last separator is "and", all other separators are ",". This simple rule can be applied to any number of items.

You can get this effect by simply counting the number of non-zero items. As I mentioned in comment, put your data in an array so you can simply iterate over it. This means your output fields should also be in an array so you only display only the ones you want in sequence.

Happy to provide code if you would provide an example of your HTML, but you should be able to figure this out yourself from these simplified rules. :)

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
1

You can make an error with functions that correspond the then blocks of the code, and then calculate the index for the array like this:

$index = 4*(signCount%2) + 2*(initCount%1) + (otherCount%2);
$then[$index]();
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
1

Update: An easier and simpler solution is to just concatenate your 3 variables (1 for true, 0 for false):

var mycode = "" + (signCount) ? "1":"0" + (initCount)?"1":"0" + (otherCount)?"1":"0"; // Concatenate as string
switch(mycode) {
case "111":
    init_class.html(' and ').fadeIn();
    sign_class.html(' , ').fadeIn();
    break;
case "110":
    init_class.html('').fadeOut();
    sign_class.html(' and ').fadeIn();
    break;
case "101":
    init_class.html('').fadeOut();
    sign_class.html(' and ').fadeIn();
    break;
case "100":
    init_class.html('').fadeOut();
    sign_class.html('').fadeOut();
    break;
case "011":
    init_class.html(' and ').fadeIn();
    sign_class.html('');
    break;
case "010":
    init_class.html('').fadeOut();
    sign_class.html('').fadeOut();
    break;
case "001":
    init_class.html('').fadeOut();
    sign_class.html('').fadeOut();
    break;
}

Original answer: This is a lot easier to follow through and notice possible mistakes:

if (signCount) {
    if(initCount) {
        if(otherCount) {
            init_class.html(' and ').fadeIn();
            sign_class.html(' , ').fadeIn();
        }
        else {
            init_class.html('').fadeOut();
            sign_class.html(' and ').fadeIn();
        }
    }
    else {
        if(otherCount) {
            init_class.html('').fadeOut();
            sign_class.html(' and ').fadeIn();
        }
        else {
            init_class.html('').fadeOut();
            sign_class.html('').fadeOut();
        }
    }
}
else {
    if (initCount) {
        if(otherCount) {
            init_class.html(' and ').fadeIn();
            sign_class.html('');
        }
        else {
            init_class.html('').fadeOut();
            sign_class.html('').fadeOut();
        }
    }
    else {
        if(otherCount) {
            init_class.html('').fadeOut();
            sign_class.html('').fadeOut();
        }
    }
}

Other then that, I'm afraid there is no easy way to simplify this knot.

user1853181
  • 813
  • 6
  • 12
  • Your switch assumes they only have a count of 0 or 1 (I gather they are values of 0 *or greater*). – iCollect.it Ltd Jan 15 '14 at 10:03
  • The OP is interested only if the values are different then 0, so this seems valid. Added conversion of values to boolean to the answer. Thanks. – user1853181 Jan 15 '14 at 10:04
1

How about this option?

$arr = array(
    array( 1, 1, 1 ), array( 1, 1, 0 ), array( 1, 0, 0 ), array( 0, 0, 0 ),
    array( 0, 0, 1 ), array( 0, 1, 1 ), array( 1, 0, 1 ), array( 0, 1, 0 )
);
$option = array_search( array($signCount?1:0, $initCount?1:0, $otherCount?1:0 );

switch( $option, $arr ) ) {
    case 0:
        init_class.html(' and ').fadeIn();
        sign_class.html(' , ').fadeIn();
        break;
    case 1:
    case 6:
        init_class.html('').fadeOut();
        sign_class.html(' and ').fadeIn();
        break;
    case 2:
    case 4:
    case 7:
        init_class.html('').fadeOut();
        sign_class.html('').fadeOut();
        break;
    case 3: // none
    break;
    case 5:
        init_class.html(' and ').fadeIn();
        sign_class.html('');
        break;
}
Peon
  • 7,902
  • 7
  • 59
  • 100
0

Try this. I have just use || for some of the conditions since they are doing the same job anyway.

Specifically this job

init_class.html('').fadeOut();
sign_class.html(' and ').fadeIn();

and this job

init_class.html('').fadeOut();
sign_class.html('').fadeOut();

are being called several times in your code. So I have just use || for those conditions.

if ((signCount != 0 && initCount != 0 && otherCount == 0) || (signCount != 0 && initCount == 0 && otherCount != 0))
{
    init_class.html('').fadeOut();
    sign_class.html(' and ').fadeIn();
}
else if (signCount == 0 && initCount != 0 && otherCount != 0)
{
    init_class.html(' and ').fadeIn();
    sign_class.html('');
}
else if (signCount != 0 && initCount != 0 && otherCount != 0)
{
    init_class.html(' and ').fadeIn();
    sign_class.html(' , ').fadeIn();
}
else if ((signCount != 0 && initCount == 0 && otherCount == 0) || (signCount == 0 && initCount != 0 && otherCount == 0) || (signCount == 0 && initCount == 0 && otherCount != 0))
{
    init_class.html('').fadeOut();
    sign_class.html('').fadeOut();
}
rccoros
  • 590
  • 9
  • 19