tags:

views:

233

answers:

6

I find myself writing code such as:

foreach($array as $key => $value) {
    switch($key) {
        case 'something':
            doSomething($value);
            break;
        case 'somethingelse':
            doSomethingElse($value);
            break;
    }
}

Is there a better way to go about this? Seems dirty to me, but I might just be over thinking it.

The only other alternative that I can think of is an if statement for each key, which doesn't seem any better. I.e. :

if($array[0] == 'something') {
    doSomething($array[0]);
}
if($array[1] == 'somethingelse') {
    doSomethingElse($array[1]);
}

(or something like that)

I can post exact code if needed, but this is the general outline of what happens. Please critique away, but remember that I'm looking for help here. So if I'm doing something egregiously wrong, then point it out.

+3  A: 

I tend to use the switch in the foreach loop. IMHO is less dirty than a bunch of if .

You can put your switch in a other function, like :

foreach($array as $key => $value) {
   doTransaction($key , $value);
}

...

function doTransaction($key, $value){
     switch($key) {
        case 'something':
            doSomething($value);
            break;
        case 'somethingelse':
            doSomethingElse($value);
           break;
    }
}
Nettogrof
A: 

Try this:

Run through each version - with the switch and with the if - a million times. Time each run.

Let us know which one runs faster.

inked
I'm not looking for optimization techniques, rather better (if they exist) design techniques.
Magic Hat
A: 

There is (at least) another possibility: use a dictionary lookup for dispatching work to a function.

Lookup-up the function using $key as "key", retrieve function reference and apply it with $value as parameter.

Forgive me but my PHP-fu is a bit rusty.

jldupont
A: 

Nothing wrong with that.

If you've only got 2 or 3 items, I'd go with the if just for the sake of code complexity. If you've got more than 5 I'd definately go with the switch...

DOOManiac
+5  A: 

Mapping your values to keys in a dictionary/associative array is a common approach for this situation (as @jldupont has mentioned) -- not just in PHP but in many dynamic languages with associative arrays. For example, Python and Lua don't even have a switch statement -- this is pretty much the only way to emulate a switch.

Consider this approach:

<?
$arr[] = "bye";
$arr[] = "hi";

function sayHi() { print("Hello.\n"); }
function sayBye() { print("Goodbye.\n"); }

$funcs["hi"] = sayHi;
$funcs["bye"] = sayBye;

foreach($arr as $k){
    $funcs[$k]();
}

?>

Output:

Goodbye.
Hello.

It's overkill when you only have two distinct values, but obviously it becomes a more worthwhile approach as the number of situations you have to cover increases.

Mark Rushakoff
This is a solution that I did not think of. Pertaining to the code that I had in mind when I posted this, this is overkill, but I can definitely think of some uses. Thanks!
Magic Hat
This is effectively a data-driven dispatch table, which has proven itself to be a most useful technique over decades of ridiculously frequent use.
Greg D
Also, a language needn't be dynamic for this approach to be useful. I've done similar things in C++, C#, and vb.net as well. :)
Greg D
+2  A: 

It's not a "bad" solution, but as always, there are alternatives. For instance, you could get rid of the switch statement and use an interpreted handler for the strings. This is similar to a list of function pointers, but you don't have to keep a list up to date to add new behavior; simply adding the new function to the handler will take care of it.

$array = array(
  "something" => "itsasecret",
  "somethingelse" => "i can't tell you",
);

class Handler {
  static function something($value) {
    printf("something: %s\n", $value);
  }

  static function somethingelse($value) {
    printf("somethingelse: %s\n", $value);
  }
}

$handler = new Handler();
foreach($array as $key => $value) {
  $handler->$key($value);
}

You'll probably need some code to sanitize the input strings and ensure that the method exists in your handler, but this might give you some ideas.

jheddings
Definitely gives me some ideas, thanks for your answer jheddings. +1
Magic Hat