Shrikant Kakani
Shrikant Kakani

Reputation: 1561

Alternative of if-else and switch statements

I have the following code in Java:

public void doSomething(int i) {
    if (i == 12) {
        // order should be same
        up();
        left();
        stop();
    }
    if (i == 304) {
        // order should be same
        right();
        up();
        stop();
    }
    if (i == 962) {
        // order should be same
        down();
        left();
        up();
        stop();
    }
}
// similar code can be done using switch case statements.
// all the function can have any functionality and might not resemble to the name given to them.

Now if I am asked not to use either of if-else and switch case statements, then what can be done? The code can be done in either Java or JavaScript.

Upvotes: 15

Views: 9122

Answers (10)

Qantas 94 Heavy
Qantas 94 Heavy

Reputation: 16020

If you can use JavaScript, you can use a object with functions:

function doSomething(i) {
  var obj = {};

  obj[12] = function () {
    // order should be same
    up();
    left();
    stop();
  };
  obj[304] = function () {
    // order should be same
    right();
    up();
    stop();
  };
  obj[962] = function () {
    // order should be same
    down();
    left();
    up();
    stop();
  };

  // apparently we can't use any conditional statements
  try {
    obj[i]();
  } catch (e) {}
}

If only if and switch statements aren't allowed, replace all the if statements with the logical AND operator (&&):

function doSomething(i) {
  (i == 12) && (
    // order should be same
    up(),
    left(),
    stop()
  );

  (i == 304) && (
    // order should be same
    right(),
    up(),
    stop()
  );

  (i == 962) && (
    // order should be same
    down(),
    left(),
    up(),
    stop()
  );
}

Upvotes: 30

netanelw
netanelw

Reputation: 121

The desired behavior can be achieved in JAVA by playing with the short-circuit of the logical AND operator as follows:

public static Boolean seq12() {
    // order should be same
    up();
    left();
    stop();
    return true;
}
public static Boolean seq304() {
    // order should be same
    right();
    up();
    stop();
    return true;
}
public static Boolean seq962() {
    // order should be same
    down();
    left();
    up();
    stop();
    return true;
}

public static void doSomething(int i) {
    Boolean tmp;
    tmp = (i == 12 && seq12());
    tmp = (i == 304 && seq304());
    tmp = (i == 962 && seq962());
}

This code is pretty straight-forward and relies on the fact that the logical AND operator only evaluates the second operand if the first one is true.

Upvotes: 0

Eric
Eric

Reputation: 684

This problem could be solved using OOP techniques.

In java it would look like this:

public abstract class AObject{
   public abstract  void doSomething();
   public void  up(){
      //do something here
   }
   public void down(){
      //do something here
   }
   public void left(){
      //do something here
   }
   public void right(){
      //do something here
   }       
   public void stop(){
      //do something here
   }     
}


public class AObject12 extends AObject{
   public void doSomething(){
      up();
      left();
      stop();
   }
}

public class AObject304 extends AObject{
   public void doSomething(){
      right();
      up();
      stop();
   }
}

public class AObject962 extends AObject{
   public void doSomething(){
      down();
      left();
      up();
      stop();
   }
}

Executing doSomething on a instance of a concrete class will trigger the appropriate behavior. So no more if/else is necesary. See code below for an example:

AObject A12 = new AObject12();
A12.doSomething();
// Will run Up left stop in that order

AObject A304 = new AObject304();
A304.doSomething();
// Will run right Up stop in that order

AObject A962 = new AObject962();
A962.doSomething();
// Will run down left up stop in that order

Some more info on this kind of programming can be found here: http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29

If you would like to be able to change the behavior of the object dynamicly you could consider applying a state pattern: http://en.wikipedia.org/wiki/State_pattern

Upvotes: 1

marksk
marksk

Reputation: 49

Wahahahahaha, you saved my day :) This should work, no way to test right now..

public void doSomething(int i) {

try {
    int x = 1/(12-i); // fails for i==12
} catch (ArithmeticException e) {
        up();
        left();
        stop();
}

and so on, enjoy!

Upvotes: 4

Salman Arshad
Salman Arshad

Reputation: 272256

Here is a simple way to accomplish this in JavaScript:

function up()    { console.log("up");    }
function down()  { console.log("down");  }
function left()  { console.log("left");  }
function right() { console.log("right"); }
function stop()  { console.log("stop");  }

var fnmaps = {
    12:  [up, left, stop],
    304: [right, up, stop],
    962: [down, left, up, stop]
};

function doSomething(i) {
    var fnmap = fnmaps[i] || [], j;
    for (j = 0; j < fnmap.length; j++) {
        fnmap[j]();
    }
}

doSomething(12);
doSomething(304);
doSomething(962);

Functions can be added/ordered simply by editing the map variable.

Upvotes: 17

senseiwu
senseiwu

Reputation: 5279

In Java, this should work..

public class IfTest {

    public static void main(String[] args) {
        IfTest ifTest = new IfTest();

        ifTest.doSomething(12);
        ifTest.doSomeThingWithoutIf(12);

        ifTest.doSomething(304);
        ifTest.doSomeThingWithoutIf(304);

        ifTest.doSomething(962);
        ifTest.doSomeThingWithoutIf(962);

        ifTest.doSomething(42);
        ifTest.doSomeThingWithoutIf(42);
    }

    public void doSomeThingWithoutIf(int i) {


        boolean x = i == 12 ? f12() : (i == 304 ? f304() : (i == 962 ? f962() : false));
    }

    public boolean f12() {

        up();
        left();
        stop();

        return true;
    }

    public boolean f304() {

        right();
        up();
        stop();
        return true;
    }

    public boolean f962() {

        down();
        left();
        up();
        stop();

        return true;
    }

    public void doSomething(int i) {

        if(i == 12) {
            // order should be same
            up();
            left();
            stop();
        }

        if(i == 304) {
            // order should be same
            right();
            up();
            stop();
        }

        if(i == 962) {
            // order should be same
            down();
            left();
            up();
            stop();
        }
    }

    private boolean retfalse() {
        return false;
    }

    private void down() {
        System.out.println("down");
    }

    private void right() {
        System.out.println("right");
    }

    private void stop() {
        System.out.println("stop");
    }

    private void left() {
        System.out.println("left");
    }

    private void up() {
        System.out.println("up");
    }
}

Upvotes: 0

opp
opp

Reputation: 75

Then do it with while and break, there is no other way without condition check

public void doSomething(int i) {

while(i == 12) {
// order should be same
    up();
    left();
    stop();
break;
    }

while(i == 304) {
// order should be same
    right();
    up();
    stop();
break;
    }

while(i == 962) {
// order should be same
    down();
    left();
    up();
    stop();
break;
    }
}

Upvotes: 4

user2575725
user2575725

Reputation:

for js u may try this:

// define ur actions here
var actions = {
  "12" : function () { up(); left(); stop(); },
  "304" : function () { right(); up(); stop(); },
  "962" : function () { down(); left(); up(); stop(); }
};

function doSomething(i) {
  var fn = actions[i];
  try {
    fn();
  } catch (err) {
    console.error(err);
  }
}
//
doSomething(12); //invoke here

Upvotes: 2

yshavit
yshavit

Reputation: 43391

You can make a dictionary of input-to-action. In Java this would be a Map<Integer, Runnable>, with, for instance*:

map.put(12, () -> {
    up();
    left();
    stop();
});

Then, you can get the appropriate Runnable and run it:

Runnable action = map.get(i);
if (action != null) {
    action.run();
} else {
    // some default action
    // This is the "default" case in a switch, or the "else" in an if-else
}

The if-else there isn't strictly necessary, but without it, you'll get a NullPointerException if i isn't an expected value — that is, one of the values you put into the map.

The idea is similar in JavaScript, though with objects instead of Maps, functions (probably anonymous) instead of Runnables, etc.


This code is for Java 8. In Java 7 and below, you'd do:

map.put(12, new Runnable() {
    @Override
    public void run() {
        up();
        left();
        stop();
    }
});

Upvotes: 12

Mohsen Kamrani
Mohsen Kamrani

Reputation: 7457

Look, naturally you should inspect a conditional statement with a conditional expression! Now, if you don't want to do this, you can do it unnaturally like this:

first do this for all methods (up,down,...)

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
  // ...
} catch (NoSuchMethodException e) {
  // ...
}

instead of an integer that you pass to the doSomething, use an array containing name of the methods that you want to call and inside a for loop call each method this way:

Then you invoke that method by calling

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {

Unfortunately Java has not delegates!

Upvotes: 1

Related Questions