homepage Welcome to WebmasterWorld Guest from 54.166.128.254
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
Simplifying complex if/else statements
ocon

5+ Year Member



 
Msg#: 4506185 posted 10:22 pm on Oct 9, 2012 (gmt 0)

Sometimes I find myself needing to test for:

if($a<15 && $b<1.2){Scenario A;}
else if($a<23 && $b<2.6){Scenario B;}
else if($a<36 && $b<3.4){Scenario C;}
else{do Scenario D;}

Other times I need to test for:

if($a<23 && $b<2.6){Scenario B;}
else if($36 && $b<3.4){Scenario C;}
else{Scenario D;}

And still, sometimes I need to test for:

else if($36 && $b<3.4){Scenario C;}
else{Scenario D;}

In total there are 8 different scenarios that I need to test for in each item inside an array loop. Before I would test for each scenario individually, but that added up quickly for large arrays. Then I realized I could run a simple test once before the loop and find out which subset of specific scenarios I need to test for inside the loop; reducing the number of tests from 8 to maybe just 2.

Lets say I need to test for scenarios ABC&D, other times BC&D, C&D, EF&G, F&G, and sometimes I know right away its H.

How could I structure the inside of my loop so I don't need to test each scenario individually (like I'm doing now) or without having to repeat the lines of test code over and over?

 

swa66

WebmasterWorld Senior Member swa66 us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 4506185 posted 9:56 am on Oct 10, 2012 (gmt 0)

There's one thing about else if vs. elseif. Although in PHP they are mostly the same. But I've never felt comfortable with leaving the curly braces off of a branch as the else if is actually doing.

Ref: [php.net...]

With the kind of tests you have it might be hard to use, but there's also the switch statement in PHP.

Ref: [php.net...]


So maybe you need once to determine the scenario you're in, store the scenario in a variable and then use switch statements from there on.

Ref: [php.net...]


Something like:


if ($a<15 && $b<1.2) {
$scenario='A';
} elseif ($a<23 && $b<2.6) {
$scenario='B';
} elseif ($a<36 && $b<3.4) {
$scenario='C';
} else {
$scenario='D';
}

//And then where you need it:

switch ($scenario) {
case 'A':
echo 'executing A';
break;
case 'B':
echo 'executing B';
break;
default:
echo 'executing other scenario';
break;
}

Dinkar

10+ Year Member



 
Msg#: 4506185 posted 5:00 pm on Oct 12, 2012 (gmt 0)

If I understood your question, the solution may be to create functions for each scenario

function scenario A
function scenario B
function scenario C
function scenario D
etc etc

Then call those function as required

switch ($scenario) {
case 'AB':
function scenario A;
function scenario B;
break;
case 'BHC':
function scenario B;
function scenario H;
function scenario C;
break;
default:
function scenario default;
break;
}

vincevincevince

WebmasterWorld Senior Member vincevincevince us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 4506185 posted 5:49 am on Nov 1, 2012 (gmt 0)

The other way:


$data=... your data;
$scenarios=NULL Array() of same size (I assume a 1D array here)
//first test
foreach ($data as $pointer=>$datum)
{
if ($scenarios[$pointer]!==NULL) continue;
if (testA($datum)) $scenarios[$pointer]="A";
}
//second test
foreach ($data as $pointer=>$datum)
{
if ($scenarios[$pointer]!==NULL) continue;
if (testB($datum)) $scenarios[$pointer]="B";
}
//third test
foreach ($data as $pointer=>$datum)
{
if ($scenarios[$pointer]!==NULL) continue;
if (testC($datum)) $scenarios[$pointer]="C";
}
//final test
foreach ($data as $pointer=>$datum)
{
if ($scenarios[$pointer]!==NULL) continue;
$scenarios[$pointer]="D"; //catch all
}


The basic approach is to loop the $data repeatedly, each time only testing those $data points which have not yet been assigned a $scenario. Put in the tests which will recognise the largest number first.

If you were careful, you could depopulate (unset()) $data points as you go and so automatically skip the records you know about. Be careful you don't accidentally re-index the array in your work though. That would avoid the NULL check.

lucy24

WebmasterWorld Senior Member lucy24 us a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



 
Msg#: 4506185 posted 10:06 pm on Nov 1, 2012 (gmt 0)

More information!

When you say "array loop" do you mean that where your example has $a and $b it's really something like $a[0], $a[1], $a[2] and so on up to $a[googol]? Do the terms always come in pairs, like $a[0] with $b[0] and so on? Are they constant? That is: they're variables, duh, but does their value change in the course of the code? Are your consecutive tests always nested as in your example, so anything that meets test 3 (< some number) automatically meets test 2 (< some smaller number)?

All the questions are because I'm thinking along the lines of taking the if/then material and putting it right into the array itself. That is: run the test once, and set $c() based on its results.

The code itself is then structured as a "switch" on $c[your-current-number], with
case x: blahblah;
case y: blahblah;
case z: blahblah;
OR, elsewhere,
case x: case y: blahblah;
case z: blahblah;
depending on how many scenarios you're using for that specific function.

But that's based on assumptions about your overall pattern that may not be valid in the first place.

:: thinking longingly of Basic dialect that let you use "case" without an argument ::

vincevincevince

WebmasterWorld Senior Member vincevincevince us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 4506185 posted 12:15 am on Nov 2, 2012 (gmt 0)

Hi Lucy, I had assumed from your talk of 'large arrays' that you were trying to process large arrays of data to find the scenarios. Perhaps I have got it wrong!

By array loop, I meant only to have the data in an array, and then loop through the array. The matching $scenarios array would be of the same size, and used for storing data about scenarios already identified.

The 'nesting' in my example would need careful arrangements of tests.

lucy24

WebmasterWorld Senior Member lucy24 us a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



 
Msg#: 4506185 posted 7:23 am on Nov 2, 2012 (gmt 0)

... and when you say "Lucy" you mean "ocon" (the OP, the guy with the problem). A simple transposition, a mere matter of cat walking across keyboard...

Oh, and conversely when I say "you" in the previous post, I also mean the OP, not, er, you. Even if you're both talking about arrays.

And, uhm, as long as I'm here. When I say
anything that meets test 3 (< some number) automatically meets test 2 (< some smaller number)

I mean, of course,
anything that meets test 2 (< some number) automatically meets test 3 (< some larger number)


I've really got to stop relying on the cat to proofread my posts.

vincevincevince

WebmasterWorld Senior Member vincevincevince us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 4506185 posted 3:39 pm on Nov 2, 2012 (gmt 0)

Ah yes, sorry - my confused mistake

jadebox

10+ Year Member



 
Msg#: 4506185 posted 6:14 pm on Nov 7, 2012 (gmt 0)

:: thinking longingly of Basic dialect that let you use "case" without an argument ::


Do you mean something like this?


switch (true)
{
case ($a < 15 && $b < 1.2):
doScenarioA();
break;
case ($a < 23 && $b < 2.6):
doScenarioB();
break;
' ... and so on ...
}

lucy24

WebmasterWorld Senior Member lucy24 us a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



 
Msg#: 4506185 posted 10:15 pm on Nov 7, 2012 (gmt 0)

Oh, gosh, can you do that?

:: woo hoo ::

jadebox

10+ Year Member



 
Msg#: 4506185 posted 9:48 pm on Nov 8, 2012 (gmt 0)

"Oh, gosh, can you do that?"

Yep. As in the example, using SWITCH like that can result in cleaner code than using IF followed by a bunch of ELSE IFs.

jadebox

10+ Year Member



 
Msg#: 4506185 posted 9:56 pm on Nov 8, 2012 (gmt 0)

As an aside ... the "switch(true)" thing works in PHP because PHP implements the case structure as a series of IFs. PHP compares the switch value to each case expression until one matches.

Other languages use the "switch" value as an index into a table. Only the switch value is determined at run time. This allows the compiled code to quickly jump to the matching case. In those languages, the switch structure is much more efficient. But it's not as flexible since the case values have to be constants.

penders

WebmasterWorld Senior Member penders us a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



 
Msg#: 4506185 posted 12:20 am on Nov 11, 2012 (gmt 0)

Perhaps...

// Declare scenarios (A..H = 8) 
$scenarios = array (
'A' => array (15, 1.2), // $a, $b
'B' => array (23, 2.6),
'C' => array (36, 3.4),
// D, E, F, G and H
);

// Example data (large array)
$data = array (
array (10, 1.8), // $a, $b
array (24, 3.0),
array (40, 2.3),
// etc.
);

// Run test to determine which subset of scenarios to test for
// - based on $data
$scenariosToTest = 'ABCD';
$lastScenarioId = $scenariosToTest[strlen($scenariosToTest)-1];

// Step through data and check scenarios
foreach ($data as $row) {
// Step through scenarios to test (subset)
foreach (str_split($scenariosToTest) as $scenarioId) {
// Reached last scenario to test? (ELSE)
// Could combine into check below or omit entirely and allow to fall through if it fails
if ($scenarioId == $lastScenarioId) {
break;
}

// $row[0] is $a / $row[1] is $b from OP's example
if (($row[0] < $scenarios[$scenarioId][0]) && ($row[1] < $scenarios[$scenarioId][1])) {
break;
}
}
// Do something with resulting scenario A, B, C, etc.
echo $scenarioId;
}


Outputs: BCD

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved