I don't want to repeat the same statements over and over again.
What is the best way to do this?
<?php
if ($a = '3'){
statement 1;
statement 2;
statement 3;
}else if ($a = '2'){
statement 1;
statement 2;
}else if ($a = '1'){
statement 1;
}
?>
To avoid repetitions, you can code:
<?php
($a == '3' or $a == '2' or $a == '1') and statement 1;
($a == '3' or $a == '2' ) and statement 2;
($a == '3' ) and statement 3;
?>
Or, that is the same:
<?php
if ($a == '3' or $a == '2' or $a == '1') { statement 1 ; }
if ($a == '3' or $a == '2' ) { statement 2; }
if ($a == '3' ) { statement 3; }
?>
Also, take a look to Switch statement
Quoting php doc:
The following two examples are two different ways to write the same
thing, one using a series of if and elseif statements, and the other
using the switch statement:
<?php
if ($i == 0) {
echo "i equals 0";
} elseif ($i == 1) {
echo "i equals 1";
} elseif ($i == 2) {
echo "i equals 2";
}
switch ($i) {
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
}
?>
For your code:
<?php
switch ($a) {
case '3':
statement 1;
statement 2;
statement 3;
break;
case '2':
statement 1;
statement 2;
break;
case '3':
statement 1;
break;
}
?>
<?php
for ($i = 1; $i <= $a; $i++) {
echo $statement . $i;
}
As danihp mentioned, you can use switch. Here's another way without breaks. The downfall of this approach is that you need to create a case for every possible value for $a.
<?php
switch ($a) {
case '3':
statement 3;
case '2':
statement 2;
case '1':
statement 1;
break;
default:
break;
}
Related
I recently got into an argument over how switch handles comparisons, and need help settling it.
If I write a switch such as:
switch ($x){
case ($x > 5):
echo "foo";
break;
case ($x < 5):
echo "bar";
break;
default:
echo "five";
break;
}
Which if statement is it equivalent to? A or B?
// A
if ($x > 5) {
echo "foo";
} elseif ($x < 5) {
echo "bar";
} else {
echo "five";
}
// B
if ($x == ($x > 5)) {
echo "foo";
} elseif ($x == ($x < 5)) {
echo "bar";
} else {
echo "five";
}
To everyone, let me clarify:
It is equivalent to B.
It is not "both", it is not sometimes its one, sometimes it is the other, it is always B. To understand why you sometimes see results that indicate that it might be A, you need to understand how type coercion works in PHP.
If you pass in a falsey value to the "argument" of switch and you use expressions in your cases that result in a boolean value, they will only match if your expression evaluates to FALSE.
switch is basically a huge if/elseif tree that performs loose comparisons (== instead of ===) between the value passed to switch (the left side of the expression) and the expression in the cases (the right side).
This can be proved quite nicely with a variation on your code:
$x = 0;
switch ($x) {
case $x > -1: // This is TRUE, but 0 == FALSE so this won't match
echo "case 1";
case $x == -1: // This is FALSE, and 0 == FALSE so this will match
echo "case 2";
}
And if we convert that to the two if/elseif trees:
A:
$x = 0;
if ($x > -1) {
// It matches here
echo "case 1";
} else if ($x == -1) {
// and not here
echo "case 2";
}
B:
$x = 0;
if ($x == ($x > -1)) {
// It doesn't match here
echo "case 1";
} else if ($x == ($x == -1)) {
// ..but here instead
echo "case 2";
}
Your example is equivalent to B.
If you want to use comparison into your switch (and be equivalent to A), you could write this:
switch (true) { // Use true instead of $x
case ($x > 5):
echo "foo";
break;
case ($x < 5):
echo "bar";
break;
default:
echo "five";
break;
}
That switch case is equivalent to B
Edit :
If we take for example that $x is equal to 0 :
$x > 5 will evaluate to false (and 0 evaluates to false too), so the first if will print bar, but the second one will print foo.
The switch will be transformed to something like this :
switch ($x){
case false:
echo "foo";
break;
case true:
echo "bar";
break;
default:
echo "five";
break;
}
and that will print foo (same as B)
Edit 2 :
I tried it so that gave me :
with $x = 0 => switch (foo), if A (bar), if B (foo)
with $x = 5 => switch (five), if A (five), if B (five)
with $x = 7 => switch (foo), if A (foo), if B (foo)
I want to be able to create variables with a loop going up to 299. For example, I have the variable $var1 and want to be able to add from there example: $var2 - $var3 - $var4 etc.
for ( $x = 1; $x<=299; $x++ )
{
$var1 = substr($size, 0, 1);
if ($var1 == '1') { $c1 = 'COLOR1'; }
elseif ($var1 == '2') { $var1 = 'COLOR2'; }
elseif ($var1 == '3') { $var1 = 'COLOR3'; };
}
This has been bugging me for sometime.
use arrays in a better way:
for ( $x = 1; $x<=299; $x++ ) {
$var[$x] = substr($size, 0, 1);
switch($var[$x]) {
case "1": $var[$x] = 'COLOR1'; break;
case "2": $var[$x] = 'COLOR2'; break;
case "3": $var[$x] = 'COLOR3'; break;
}
// or the more simple if you follow the same rule
// $var[$x] = "COLOR".$var[$x];
}
I'm parsing some text and calculating the weight based on some rules. All the characters have the same weight. This would make the switch statement really long can I use ranges in the case statement.
I saw one of the answers advocating associative arrays.
$weights = array(
[a-z][A-Z] => 10,
[0-9] => 100,
['+','-','/','*'] => 250
);
//there are more rules which have been left out for the sake of clarity and brevity
$total_weight = 0;
foreach ($text as $character)
{
$total_weight += $weight[$character];
}
echo $weight;
What is the best way to achieve something like this?
Is there something similar to the bash case statement in php?
Surely writing down each individual character in either the associative array or the switch statement can't be the most elegant solution or is it the only alternative?
Well, you can have ranges in switch statement like:
//just an example, though
$t = "2000";
switch (true) {
case ($t < "1000"):
alert("t is less than 1000");
break
case ($t < "1801"):
alert("t is less than 1801");
break
default:
alert("t is greater than 1800")
}
//OR
switch(true) {
case in_array($t, range(0,20)): //the range from range of 0-20
echo "1";
break;
case in_array($t, range(21,40)): //range of 21-40
echo "2";
break;
}
$str = 'This is a test 123 + 3';
$patterns = array (
'/[a-zA-Z]/' => 10,
'/[0-9]/' => 100,
'/[\+\-\/\*]/' => 250
);
$weight_total = 0;
foreach ($patterns as $pattern => $weight)
{
$weight_total += $weight * preg_match_all ($pattern, $str, $match);;
}
echo $weight_total;
*UPDATE: with default value *
foreach ($patterns as $pattern => $weight)
{
$match_found = preg_match_all ($pattern, $str, $match);
if ($match_found)
{
$weight_total += $weight * $match_found;
}
else
{
$weight_total += 5; // weight by default
}
}
You can specify the character range using regular expression. This saves from writing a really long switch case list. For example,
function find_weight($ch, $arr) {
foreach ($arr as $pat => $weight) {
if (preg_match($pat, $ch)) {
return $weight;
}
}
return 0;
}
$weights = array(
'/[a-zA-Z]/' => 10,
'/[0-9]/' => 100,
'/[+\\-\\/*]/' => 250
);
//there are more rules which have been left out for the sake of clarity and brevity
$total_weight = 0;
$text = 'a1-';
foreach (str_split($text) as $character)
{
$total_weight += find_weight($character, $weights);
}
echo $total_weight; //360
Much different ways to do this.
$var = 0;
$range_const = range(10,20);
switch ($var) {
case 1: $do = 5; break; # 1
case 2: $do = 10; break; # 2
case 3:
case 4:
case 5: $do = 15; break; # 3, 4, 5
default:
if ($var > 5 && $var < 10) { # High performance (6..9)
$do = 20;
} else if (in_array($var, $range_const, true)) { # Looks clear (10..20)
$do = 25;
} else { # NOT in range 1..20
$do = -1;
}
}
print($do);
There no direct range X..Y compares because $var checks to true in each step, but this allows do some nice cheating like this...
$in = create_function('$a,$l,$h', 'return $a>=$l && $a<=$h;');
$var = 4;
switch (true) {
case ($var === 1): echo 1; break;
case ($var === 2): echo 2; break;
case $in($var, 3, 5): echo "3..5"; break;
case $in($var, 6, 10): echo "6..10"; break;
default: echo "else";
}
If you have a more complex conditions, you can wrap them inside a function. Here's an oversimplified example:
$chartID = 20;
$somethingElse = true;
switch (switchRanges($chartID, $somethingElse)) {
case "do this":
echo "This is done";
break;
case "do that":
echo "that is done";
break;
default:
echo "do something different";
}
function switchRanges($chartID, $somethingElse = false)
{
if (in_array($chartID, [20, 30]) && $somethingElse === true) {
return "do this";
}
if (in_array($chartID, [20, 50]) && $somethingElse === false) {
return "do that";
}
}
I think I would do it in a simple way.
switch($t = 100){
case ($t > 99 && $t < 101):
doSomething();
break;
}
This is very strange but below is my case statement:
switch($grade){
case ($average >70):
$grade = 'A';
break;
case ($average >=60 && $average <=69):
$grade = 'B';
break;
case ($average >=50 && $average <=59):
$grade = 'C';
break;
};
So if its 70+ it is grade A, 60-69 grade B, 50-59 grade C.
But instead it outputting this: 60+ grade A, 50-59 grade B, 40-49 grade C.
Why is it doing this because function seems correct?
echo "<p><strong>Average Mark:</strong> $average</p>";
echo "<p><strong>Average Grade:</strong> $grade</p>";
As others mentioned in comments, the "condition" in a case should be a static value, not a logical expression.
Also, the value you're switching on (in your case, $grade) should is the one you're testing. You appear to be using it as a hint about what variable you're assigning.
The simplest way to fix your code would be to use an if-elseif-else construct:
if ($average >70)
$grade = 'A';
elseif ($average >=60 && $average <=69)
$grade = 'B';
elseif ($average >=50 && $average <=59)
$grade = 'C';
However, to be perverse, and to illustrate how a switch statement works, you could also do the following:
switch(true){
case ($average >70):
$grade = 'A';
break;
case ($average >=60 && $average <=69):
$grade = 'B';
break;
case ($average >=50 && $average <=59):
$grade = 'C';
break;
};
In this example I'm comparing the value true to each of the cases in turn, where each of those case-values is actually the result of evaluating a boolean expression. The first expression whose value matches true will fire.
Probably not much help, if you don't understand switch statements.
Edit: I just noticed that there's a gap in the logic: what if someone's average is exactly 70? Using a cascading statement like a switch or if-else, you can eliminate some of the redundant (and in this case damaging) code, thus:
if ($average >=70)
$grade = 'A';
elseif ($average >=60)
$grade = 'B';
elseif ($average >=50)
$grade = 'C';
// ...
else
$grade = 'F';
...and so on, to whatever lowest grade you're using.
For those of you saying switch the variable you $average, you are wrong. The only reason it is evaluating in that instance is because switch uses loose comparison, so it is saying that $average being set is true and comparing it to the conditionals, all of which will be either true or false. Previously, using $grade which was unset was evaluating the switch to false because in loose comparison, a variable which is unset will throw a notice and return false.
While I recommend using if-then-else, the proper answer for using a switch statement in this case is as follows:
switch (true) {
case ($average >= 70):
$grade = 'A';
break;
case ($average >= 60 && $average < 70):
$grade = 'B';
break;
case ($average >= 50 && $average < 60):
$grade = 'C';
break;
}
Like said above, every statement will return either true or false. The idea is that only one statement should ever return true at one time, thus the switch statement will match it's value of true to the one statement that passed and execute that code only, since all of the other ones are false and didn't match.
You should use if/else - statements:
if($average >70)
{
$grade = 'A';
} else if($average >=60 && $average <=69)
{
$grade = 'B';
} else if($average >=50 && $average <=59)
{
$grade = 'C';
}
Edit: Alternatively you can calculate the $grade value (50-100 in this example):
$grades = "CBAAA";
$grade = $grades[(int)($average/10) - 5];
The switch loop compares the cases. If you really want to use switch for the job (and not if / elseif / else), then you can to it with a switch that compares against TRUE:
switch(TRUE)
{
case $average > 70:
$grade = 'A';
break;
case $average >= 60 && $average <= 69:
$grade = 'B';
break;
case $average >= 50 && $average <= 59:
$grade = 'C';
break;
default:
throw new Exception(sprintf('Unable to map average (%d) to a grade.', $average));
}
A sample of what I'm trying to do will be more explicit:
var_dump($opti_point); //int 0
if ($opti_point>=0 && $opti_point < 25) echo 'good';//echoing good
switch ($opti_point) {
case ($opti_point>= 0 && $opti_point < 25):
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50):
echo 'we are in this case'; // This case is called !
$test = 2;
break;
default:
test = 0;
break;
}
Is there a trick here ?
thx
You cannot put comparisons inside "case" unfortunately...
A switch is only used when a value can have one of a limited number of values like so:
switch ( $val ) {
case 1:
echo "Got 1";
break;
case 2:
echo "Got 2";
break;
default:
echo "Got invalid value";
}
A workaround would be to use:
switch (true) {
case ($opti_point>= 0 && $opti_point < 25):
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50):
echo 'we are in this case';
$test = 2;
break;
default:
test = 0;
break;
}
Which will work, but is a bit ugly...
Also, you're missing a single quote in echo we are in this case'; which should be echo 'we are in this case';
You should be using an if instead =)
You need to change the switch argument to true of false if you do comparison liek that in the cases.
You are not comparing what you think you are comparing. This is the code I think you want.
var_dump($opti_point); //int 0
if ($opti_point>=0 && $opti_point < 25) {
$test = 0;
echo 'You are now here!';
} elseif ($opti_point >= 25 && $opti_point < 50) {
$test = 2;
} else {
test = 0;
}
In your example, you are comparing the result of the logical statement...
($opti_point>=0 && $opti_point < 25) // true
To the value of $opti_point
0 // false
So PHP is actually converting what you think in an integer into a boolean to compare it with the result of the conditional statement.
I think that's a very bad way to use a switch statement, you should not put conditional sentences in the cases... In fact, I'm sure that that would be illegal in other languages and I'm not sure that it should work in PHP. Use a number of concatenated if-else conditions instead:
if ($i == 0) {
echo "i equals 0";
} elseif ($i == 1) {
echo "i equals 1";
} elseif ($i == 2) {
echo "i equals 2";
}
I'll go true the code with you
var_dump($opti_point); //int 0 , or false --- you should use TRUE
if ($opti_point>=0 && $opti_point < 25) echo 'good';//echoing good
switch ($opti_point) { // chose the case that is $opti_point (0 or false)
case ($opti_point>= 0 && $opti_point < 25): // true, so go to next
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50): //false si this is the wan I pick
echo 'we are in this case'; // This case is called !
$test = 2;
break; // ingore the rest
default:
test = 0;
break;
}
you should use TRUE in the switch
if this is the exact code then try this
var_dump($opti_point); //int 0
if ($opti_point>=0 && $opti_point < 25) echo 'good';//echoing good
switch ($opti_point) {
case ($opti_point>= 0 && $opti_point < 25):
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50):
echo 'we are in this case'; // This case is called !
$test = 2;
break;
default:
$test = 0;
break;
}
You have a misunderstanding on how switch-case works. Case DOES NOT TEST YOUR EXPRESSION TO BE boolean TRUE!
It compares its value to 'switch' value!
Here is an explanation:
$opti_point>= 0 && $opti_point < 25 evalutes to true which integer representation is 1 and since PHP can deal with types on it's own, it turnes true to 1 and compares it with value in switch which is 0
$opti_point >= 25 && $opti_point < 50 evaluates to false which is 0 as integer, so... that's your case ;)