Reputation: 131
I am writing code for a large scale app, and there is an event where lots of if
/else
checks are required.
For example:
if (i == 1) { /* some logic */ }
else if (i == 2) { /* some logic */ }
// ...
// ...
else if (i == 1000) { /* some logic */ }
Is there a more efficient or organised way to write this?
Upvotes: 2
Views: 122
Reputation: 8417
Sounds like you have a collection of functions and you just need to use a HashMap
. i
would be index of the map. Hashmaps are useful because they find the corresponding value for a key quickly, without having to compare lots of values until a match is found.
Here is an example of a HashMap
from Any
to Any => Any
. Because Scala supports tuples, this is a completely general solution.
object Hello extends App {
import scala.collection.immutable
type F1 = (Any) => Any
val hashMap: immutable.Map[Int, F1] =
immutable.HashMap[Int, F1](
1 -> { (a: Int) => a * 2 }.asInstanceOf[F1], // Function literal that doubles it's input
2 -> { (tuple: (String, Int)) => tuple._1 * tuple._2 }.asInstanceOf[F1], // Function literal that repeats the string
1000 -> { (_: Unit) => s"The date and time is ${ new java.util.Date() }" }.asInstanceOf[F1]
)
def lookup(i: Int, args: Any): Any = hashMap(i)(args)
def report(i: Int, args: Any): Unit = println(s"$i: ${ lookup(i, args) }")
report(1, 21)
report(2, ("word ", 5))
report(1000, ())
}
Here is the output:
1: 42
2: word word word word word
1000: The date and time is Sat Dec 23 19:45:56 PST 2017
Update: Here is a version that uses an array. Notice that the indices must start at 0 for this version, not an arbitrary number as before:
object Hello2 extends App {
type F1 = (Any) => Any
val array: Array[F1] =
Array[F1](
{ (a: Int) => a * 2 }.asInstanceOf[F1], // Function literal that doubles it's input
{ (tuple: (String, Int)) => tuple._1 * tuple._2 }.asInstanceOf[F1], // Function literal that repeats the string
{ (_: Unit) => s"The date and time is ${ new java.util.Date() }" }.asInstanceOf[F1]
)
def lookup(i: Int, args: Any): Any = array(i)(args)
def report(i: Int, args: Any): Unit = println(s"$i: ${ lookup(i, args) }")
report(0, 21)
report(1, ("word ", 5))
report(2, ())
}
Output is:
0: 42
1: word word word word word
2: The date and time is Sat Dec 23 20:32:33 PST 2017
Upvotes: 2
Reputation: 45339
If you are doing 1000 distinct things in those code blocks, then the problem is logic complexity. In that case, you have no option but to code like that or to change to a switch
.
In the case of if
, the only key thing to remember is to move to the top the cases you know to be most likely/frequent.
If you aren't doing 1000 different things that have to be individually coded, then you can consider some of these options:
Break down into ranges, if that's possible:
if(i < 300): {
//do something
} else if(i < 600) {
// do another thing
}
//do the default thing
If the logic can be programmed and the value of i
can be used as an argument used to decide implementation logic, then you can use abstraction:
abstract class NumberProcessor {
protected int i;
static NumberProcessor getInstance(int i){
//Use this block to look at the number and choose one of few implementations...
//and store number in the instance
}
abstract void processNumber();
}
You can then write a few implementations based on whatever logic you can group on.
Upvotes: 1
Reputation: 167
Use a switch statement. Ex.
switch(variable) {
case 1:
//DoStuff
break;
case 2:
//DoStuff
break;
default:
//Dostuff
break;
}
Alternatively, if you know the most common case, you can break it down from there to improve algorithmic run time which may require a different approach.
Upvotes: 3